diff --git a/.appveyor/Build.sh b/.appveyor/Build.sh index 23d3fe07f..a0efff856 100755 --- a/.appveyor/Build.sh +++ b/.appveyor/Build.sh @@ -1,30 +1,30 @@ #!/usr/bin/env bash set -ex -# Creating flatpak directories -mkdir -p "${APPVEYOR_BUILD_FOLDER}/.flatpak/lib" "${APPVEYOR_BUILD_FOLDER}/.flatpak/data" "${APPVEYOR_BUILD_FOLDER}/.flatpak/bin" - +# Configure cd "$APPVEYOR_BUILD_FOLDER/src_rebuild" - ./premake5 gmake2 - cd project_gmake2_linux +# Build for config in debug_x86 release_x86 release_dev_x86 do make config=$config -j$(nproc) done -find ${APPVEYOR_BUILD_FOLDER}/src_rebuild/bin -name 'REDRIVER2*' -exec cp -t ${APPVEYOR_BUILD_FOLDER}/.flatpak/bin {} + +cd ${APPVEYOR_BUILD_FOLDER} + +# Creating flatpak directories +mkdir -p "${APPVEYOR_BUILD_FOLDER}/.flatpak/lib" "${APPVEYOR_BUILD_FOLDER}/.flatpak/data" "${APPVEYOR_BUILD_FOLDER}/.flatpak/bin" +find ${APPVEYOR_BUILD_FOLDER}/src_rebuild/bin/Release -name 'REDRIVER2*' -exec cp -t ${APPVEYOR_BUILD_FOLDER}/.flatpak/bin {} + # Copy missing libraries in the runtime -for lib in libjpeg libopenal libsndio libbsd +for lib in libjpeg libopenal do cp -Lf $(ldd "${APPVEYOR_BUILD_FOLDER}/src_rebuild/bin/Release/REDRIVER2" | awk '/ => / { print $3 }' | grep ${lib}) "${APPVEYOR_BUILD_FOLDER}/.flatpak/lib" done cp -r "${APPVEYOR_BUILD_FOLDER}/data" "${APPVEYOR_BUILD_FOLDER}/.flatpak/" -cd ${APPVEYOR_BUILD_FOLDER} # Editing metadatas with the current version export APPVEYOR_BUILD_DATE=$(date "+%Y-%m-%d") diff --git a/.appveyor/Install.sh b/.appveyor/Install.sh index afe2e9760..7ca639f0b 100755 --- a/.appveyor/Install.sh +++ b/.appveyor/Install.sh @@ -26,7 +26,7 @@ export XDG_DATA_DIRS="/var/lib/flatpak/exports/share:${HOME}/.local/share/flatpa flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo # Adding Platform/SDK for the Linux flatpak release -flatpak --user install flathub org.freedesktop.Platform/x86_64/20.08 -y -flatpak --user install flathub org.freedesktop.Sdk/x86_64/20.08 -y -flatpak --user install flathub org.freedesktop.Sdk.Compat.i386/x86_64/20.08 -y -flatpak --user install flathub org.freedesktop.Sdk.Extension.toolchain-i386/x86_64/20.08 -y +flatpak --user install flathub org.freedesktop.Platform/x86_64/22.08 -y +flatpak --user install flathub org.freedesktop.Sdk/x86_64/22.08 -y +flatpak --user install flathub org.freedesktop.Sdk.Compat.i386/x86_64/22.08 -y +flatpak --user install flathub org.freedesktop.Sdk.Extension.toolchain-i386/x86_64/22.08 -y diff --git a/.flatpak/io.github.opendriver2.Redriver2.appdata.xml b/.flatpak/io.github.opendriver2.Redriver2.appdata.xml index 52950d8fc..c08e84b9b 100644 --- a/.flatpak/io.github.opendriver2.Redriver2.appdata.xml +++ b/.flatpak/io.github.opendriver2.Redriver2.appdata.xml @@ -4,9 +4,9 @@ MIT MIT REDRIVER2 - Driver 2 Playstation game reverse engineering effort + Driver 2 - Back On The Streets / The Wheelman Is Back - Driver 2 Playstation game reverse engineering effort + Reverse-Engineered version of Driver 2. https://opendriver2.github.io Game diff --git a/.flatpak/ld.so.conf b/.flatpak/ld.so.conf new file mode 100644 index 000000000..76daf6576 --- /dev/null +++ b/.flatpak/ld.so.conf @@ -0,0 +1,5 @@ +# We just make any GL32 extension have higher priority +include /run/flatpak/ld.so.conf.d/app-*-org.freedesktop.Platform.GL32.*.conf +/app/lib32 +/app/lib/i386-linux-gnu +/lib64 \ No newline at end of file diff --git a/.flatpak/start.sh b/.flatpak/start.sh index d268502f7..7d0019d48 100644 --- a/.flatpak/start.sh +++ b/.flatpak/start.sh @@ -13,7 +13,7 @@ function importDefaultData { } if [ ! -d /var/data/DRIVER2 ]; then - zenity --error --no-wrap --text="`printf "DRIVER2 files are missing! Add the folder in:\n ${HOME}/.var/io.github.opendriver2.Redriver2/data"`" + zenity --error --no-wrap --text="`printf "DRIVER2 files are missing! Please provide DRIVER2 folder in:\n ${HOME}/.var/app/io.github.opendriver2.Redriver2/data"`" exit 0 fi diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..f6462a3b3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +FROM fedora:37 +LABEL Description="Build environment" + +ENV HOME /root + +SHELL ["/bin/bash", "-c"] + +RUN dnf update -y && \ + dnf groupinstall -y 'Development Tools' && \ + dnf install -y make gcc gcc-c++ \ + libjpeg-turbo-devel.i686 \ + glibc-devel.i686 \ + SDL2-devel.i686 \ + openal-soft-devel.i686 \ + flatpak flatpak-builder + +ENV APPVEYOR_BUILD_FOLDER=/src + +# Setting XDG_DATA_DIRS environement variable for flatpak +ENV XDG_DATA_DIRS="/var/lib/flatpak/exports/share:${HOME}/.local/share/flatpak/exports/share:$XDG_DATA_DIRS" + +# Adding the flathub repo +RUN flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + +# Adding Platform/SDK for the Linux flatpak release +RUN flatpak --user install flathub org.freedesktop.Platform/x86_64/22.08 -y +RUN flatpak --user install flathub org.freedesktop.Sdk/x86_64/22.08 -y +RUN flatpak --user install flathub org.freedesktop.Sdk.Compat.i386/x86_64/22.08 -y +RUN flatpak --user install flathub org.freedesktop.Sdk.Extension.toolchain-i386/x86_64/22.08 -y + +WORKDIR /src + +CMD ["/bin/bash"] + +# Building example: +# docker build -t builder/multiarch_build:1.0 -f Dockerfile . + +# Running example: +# docker run -it --privileged=true --rm --name=builder --mount type=bind,source=${PWD},target=/src builder/multiarch_build:1.0 bash diff --git a/PSXToolchain/README.md b/PSXToolchain/README.md index 7e18defa0..53eaf5328 100644 --- a/PSXToolchain/README.md +++ b/PSXToolchain/README.md @@ -1,10 +1,11 @@ # Playstation build toolchain -In order to start building a Playstation version of **REDRIVER2** you'll need to perform following steps: +This is an instruction to build Playstation version of **REDRIVER2** +### Windows + - Install **make** (In powershell `choco install make`) - Put **mipsel-unknown-elf** toolchain to this folder (https://github.com/majenkotech/mipsel-unknown-elf/releases) - - Install **make** - - Obtain **Psy-Q SDK** converted for *latest GCC* + - Put Nugget version of **Psy-Q SDK** - Copy (https://github.com/pcsx-redux/nugget/tree/main/common) to `/PSXToolchain/PsyQ/common` - Execute **psx_build.bat** - Install [mkpsxiso](https://github.com/Lameguy64/mkpsxiso/releases) diff --git a/PSXToolchain/psx_build.bat b/PSXToolchain/psx_build.bat deleted file mode 100644 index bebe8ea64..000000000 --- a/PSXToolchain/psx_build.bat +++ /dev/null @@ -1,25 +0,0 @@ -echo off -cls -set REDRIVER_FOLDER=%cd%\.. - -rem Make a symlink -mklink /J %REDRIVER_FOLDER%\PSXToolchain\GameSRC %REDRIVER_FOLDER%\src_rebuild - -rem Create a virtual drive -SUBST X: %REDRIVER_FOLDER%\PSXToolchain - -set PATH=%PATH%;X:\mipsel-unknown-elf\bin; - -if exist %REDRIVER_FOLDER%\PSXToolchain\CDSrc\0_CD_DATA\ ( - rem Yes -) else ( - mkdir %REDRIVER_FOLDER%\PSXToolchain\CDSrc\0_CD_DATA\ -) - -make - -rem Cleanup -rem del GameSRC -SUBST X: /D - -pause \ No newline at end of file diff --git a/PSXToolchain/psx_build.ps1 b/PSXToolchain/psx_build.ps1 new file mode 100644 index 000000000..c481b4ec9 --- /dev/null +++ b/PSXToolchain/psx_build.ps1 @@ -0,0 +1,33 @@ +$REDRIVER_FOLDER=[string](Get-Location) + "\.." +$cdDataPath = "$($REDRIVER_FOLDER)\PSXToolchain\CDSrc\0_CD_DATA\" + +Write-Host $cdDataPath + +# Make a symlink +$link_exist = Get-Item -Path "$($REDRIVER_FOLDER)\PSXToolchain\GameSRC" -ErrorAction Ignore +if (-Not $link_exist) { + New-Item -ItemType Junction -Path "$($REDRIVER_FOLDER)\PSXToolchain\GameSRC" -Target "$($REDRIVER_FOLDER)\src_rebuild" +} + +# Create a virtual drive +Invoke-Expression "SUBST X: $($REDRIVER_FOLDER)\PSXToolchain" + +# Set tools path +$envPath = $env:PATH +$env:PATH="$($envPath);X:\mipsel-unknown-elf\bin"; + +Write-Host $env:PATH + +$folder_exist = Get-Item -Path $cdDataPath -ErrorAction Ignore +if (-Not $folder_exist) { + New-Item -ItemType Directory -Path "$($REDRIVER_FOLDER)\PSX]Toolchain\CDSrc\0_CD_DATA" +} + +Write-Host "Starting build process..." + +Invoke-Expression "make" + +# Cleanup +Invoke-Expression "SUBST X: /D" + +Read-Host -Prompt "Build completed, press any key" diff --git a/appveyor.yml b/appveyor.yml index 9757870f4..876327b53 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 7.4.{build} +version: 7.8.{build} branches: only: diff --git a/data/DRIVER2/GFX/HQ/digits.tga b/data/DRIVER2/GFX/HQ/digits.tga new file mode 100644 index 000000000..356e01567 Binary files /dev/null and b/data/DRIVER2/GFX/HQ/digits.tga differ diff --git a/data/DRIVER2/GFX/HQ/fefont.fn2 b/data/DRIVER2/GFX/HQ/fefont.fn2 new file mode 100644 index 000000000..9349c4d8e Binary files /dev/null and b/data/DRIVER2/GFX/HQ/fefont.fn2 differ diff --git a/data/DRIVER2/GFX/HQ/fefont.tga b/data/DRIVER2/GFX/HQ/fefont.tga new file mode 100644 index 000000000..89b1bb79a Binary files /dev/null and b/data/DRIVER2/GFX/HQ/fefont.tga differ diff --git a/data/DRIVER2/GFX/HQ/font2.fn2 b/data/DRIVER2/GFX/HQ/font2.fn2 new file mode 100644 index 000000000..313289bec Binary files /dev/null and b/data/DRIVER2/GFX/HQ/font2.fn2 differ diff --git a/data/DRIVER2/GFX/HQ/font2.tga b/data/DRIVER2/GFX/HQ/font2.tga new file mode 100644 index 000000000..1bfe5c967 Binary files /dev/null and b/data/DRIVER2/GFX/HQ/font2.tga differ diff --git a/data/DRIVER2/LANG/EN_GAME.LTXT b/data/DRIVER2/LANG/EN_GAME.LTXT index 3cef42942..cc758c0c9 100644 --- a/data/DRIVER2/LANG/EN_GAME.LTXT +++ b/data/DRIVER2/LANG/EN_GAME.LTXT @@ -53,6 +53,7 @@ Music Volume Film Director Quick Replay Exit +Back Rotation Move Skip cutscene diff --git a/data/DRIVER2/LANG/EN_MISSION.LTXT b/data/DRIVER2/LANG/EN_MISSION.LTXT index 164ea2c98..27feec48b 100644 --- a/data/DRIVER2/LANG/EN_MISSION.LTXT +++ b/data/DRIVER2/LANG/EN_MISSION.LTXT @@ -20,7 +20,7 @@ Back to Jones Tail Jericho Pursue Jericho Escape the Brazilians -Casino getaway +Casino Getaway Beat the train Car bomb Car bomb getaway @@ -30,7 +30,7 @@ Stake Out Steal the keys C4 deal Destroy the yard -Bus crash +Bus Crush Steal the cop car Caine's cash Save Jones @@ -66,7 +66,7 @@ Lenny's getaway Lenny gets it Back in Chicago Vasquez meets Caine -Credits +The End Downtown Wrigleyville Greektown diff --git a/data/DRIVER2/LANG/FR_GAME.LTXT b/data/DRIVER2/LANG/FR_GAME.LTXT index 7c705b489..61db1d7dd 100644 --- a/data/DRIVER2/LANG/FR_GAME.LTXT +++ b/data/DRIVER2/LANG/FR_GAME.LTXT @@ -53,6 +53,7 @@ Volume de la musique Réalisateur de film Replay rapide Sortie +Retour Rotation Déplacement Passer la cinématique diff --git a/data/DRIVER2/LANG/GE_GAME.LTXT b/data/DRIVER2/LANG/GE_GAME.LTXT index a4b654774..40bd0949c 100644 --- a/data/DRIVER2/LANG/GE_GAME.LTXT +++ b/data/DRIVER2/LANG/GE_GAME.LTXT @@ -53,6 +53,7 @@ Musik Filmregisseur Wiederholung Ende +Zurück Rotation Bewegung Zwischensequenz überspringen diff --git a/data/DRIVER2/LANG/IT_GAME.LTXT b/data/DRIVER2/LANG/IT_GAME.LTXT index 743ffa01c..bfe2d350d 100644 --- a/data/DRIVER2/LANG/IT_GAME.LTXT +++ b/data/DRIVER2/LANG/IT_GAME.LTXT @@ -53,6 +53,7 @@ Volume musica Regista video Replay veloce Esci +Indietro Ruota Sposta Salta filmato diff --git a/data/DRIVER2/LANG/SP_GAME.LTXT b/data/DRIVER2/LANG/SP_GAME.LTXT index 15512eb13..397a58d18 100644 --- a/data/DRIVER2/LANG/SP_GAME.LTXT +++ b/data/DRIVER2/LANG/SP_GAME.LTXT @@ -53,6 +53,7 @@ Volumen de m Director de película Repetición rápida Salir +Atrás Rotación Mover Saltear escena diff --git a/data/config.ini b/data/config.ini index e21c80797..1ae3f6a91 100644 --- a/data/config.ini +++ b/data/config.ini @@ -2,25 +2,6 @@ # dataFolder=REDRIVER2 # dataFolder=. -# Game keyboard controls (Psy-X layer PSX mapping) -[kbcontrols_game] -cross=up -square=down -circle=right shift -triangle=space -up=NONE -down=NONE -left=left -right=right -start=escape -select=c -l1=right ctrl -r1=H -l2=A -r2=D -l3=S -r3=return - # Available controller binds (refer to SDL2 game controller) # # Axes: @@ -37,51 +18,46 @@ r3=return # leftshoulder rightshoulder # dpup dpdown dpleft dpright +# Game keyboard controls (Psy-X layer PSX mapping) +[kbcontrols_game] +cross=Up +square=Down +circle=Right Shift +triangle=Space +up= +down= +left=Left +right=Right +start=Escape +select=C +l1=Right Ctrl +r1=H +l2=A +r2=D +l3=S +r3=Return [controls_game] -# cross=a -# square=x -# circle=b -# triangle=y -# up=dpup -# down=dpdown -# left=dpleft -# right=dpright -# start=start -# select=back -# l1=leftshoulder -# r1=rightshoulder -# l2=lefttrigger -# r2=righttrigger -# l3=leftstick -# r3=rightstick -# axis_left_x=leftx -# axis_left_y=lefty -# axis_right_x=rightx -# axis_right_y=righty - -[controls_menu] -# cross=x -# square=x -# circle=b -# triangle=y -# up=dpup -# down=dpdown -# left=dpleft -# right=dpright -# start=start -# select=back -# l1=leftshoulder -# r1=rightshoulder -# l2=lefttrigger -# r2=righttrigger -# l3=leftstick -# r3=rightstick -# axis_left_x=leftx -# axis_left_y=lefty -# axis_right_x=rightx -# axis_right_y=righty - +cross=a +square=x +circle=b +triangle=y +up=dpup +down=dpdown +left=dpleft +right=dpright +start=start +select=back +l1=leftshoulder +r1=rightshoulder +l2=lefttrigger +r2=righttrigger +l3=leftstick +r3=rightstick +axis_left_x=leftx +axis_left_y=lefty +axis_right_x=rightx +axis_right_y=righty [kbcontrols_menu] cross=return @@ -97,31 +73,31 @@ start=w select=H [cdfs] -#image=install/Driver2CD1.bin -mode=1,2,2352 # track, mode, sector size. DO NOT MODIFY +image=install/Driver2CD1.bin +mode=1,2,2352 # track, mode, sector size. DO NOT MODIFY [pad] -pad1device=-1 # player 1 controller device; -1 for automatic assignment -pad2device=-1 # player 2 controller device; -1 for automatic assignment +pad1device=-1 # player 1 controller device; -1 for automatic assignment +pad2device=-1 # player 2 controller device; -1 for automatic assignment [render] windowWidth=1280 windowHeight=720 -fullscreen=0 # enable full screen mode -screenWidth=1280 # screen resolution when fullscreen is on -screenHeight=720 -vsync=1 # Prevents screen tearing in Full screen. Turn it off if you have framerate problems. +fullscreen=0 # enable full screen mode; it takes screen resolution pgxpTextureMapping=1 -bilinearFiltering=1 # "smooth" textures -pgxpZbuffer=1 # full Z-buffer on PSX polygons +bilinearFiltering=1 # "smooth" textures +pgxpZbuffer=1 # full Z-buffer on PSX polygons +vsync=1 [game] -languageId=0 # 0 = ENGLISH; 1 = ITALIAN; 2 = GERMAN; 3 = FRENCH; 4 = SPANISH; -drawDistance=1800 # 441..1800 -fieldOfView=256 # 128..384, 256 is default -disableChicagoBridges=0 # Experimental: also activate AI roads -freeCamera=1 # Press F7 in game to enable +languageId=0 # 0 = ENGLISH; 1 = ITALIAN; 2 = GERMAN; 3 = FRENCH; 4 = SPANISH; +drawDistance=1800 # 441..1800 +dynamicLights=1 # set 1 to enable dynamic street lights +fieldOfView=256 # 128..384, 256 is default +disableChicagoBridges=0 # Experimental: also activate AI roads +freeCamera=1 # Press F7 in game to enable fastLoadingScreens=1 -widescreenOverlays=1 # set 1 to see map, bars and stats aligned to screen corners -driver1music=0 # put Driver 1's MUSIC.BIN as D1MUSIC.BIN to DRIVER2\SOUNDS folder -overrideContent=0 # this enables texture and car model modding \ No newline at end of file +widescreenOverlays=1 # set 1 to see map, bars and stats aligned to screen corners +driver1music=0 # put Driver 1's MUSIC.BIN as D1MUSIC.BIN to DRIVER2\SOUND folder +overrideContent=0 # this enables texture and car model modding +userChases=RacingFreak,Snoopi,Olanov,Vortex,Fireboyd78 \ No newline at end of file diff --git a/dockerbuild.sh b/dockerbuild.sh new file mode 100755 index 000000000..6158a1a17 --- /dev/null +++ b/dockerbuild.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -ex + +docker build -t builder/multiarch_build:1.0 -f Dockerfile . +docker run -it --privileged=true --rm --name=builder --mount type=bind,source=${PWD},target=/src builder/multiarch_build:1.0 ./.appveyor/Build.sh diff --git a/io.github.opendriver.redriver2.yaml b/io.github.opendriver.redriver2.yaml index 2fa0acf17..91a6d90fd 100644 --- a/io.github.opendriver.redriver2.yaml +++ b/io.github.opendriver.redriver2.yaml @@ -1,9 +1,11 @@ ---- app-id: io.github.opendriver2.Redriver2 runtime: org.freedesktop.Platform -runtime-version: '20.08' -rename-icon: 'icon' +runtime-version: &runtime-version '22.08' +x-gl-version: &gl-version '1.4' +x-gl-versions: &gl-versions 22.08;22.08-extra;1.4 sdk: org.freedesktop.Sdk +separate-locales: false +rename-icon: 'icon' command: start.sh finish-args: - "--socket=x11" @@ -14,47 +16,66 @@ finish-args: - "--persist=." - "--allow=multiarch" - "--env=SDL_DYNAMIC_API=/app/lib/i386-linux-gnu/libSDL2-2.0.so.0" + add-extensions: org.freedesktop.Platform.Compat.i386: directory: lib/i386-linux-gnu - version: '20.08' + version: *runtime-version + org.freedesktop.Platform.Compat.i386.Debug: directory: lib/debug/lib/i386-linux-gnu - version: '20.08' + version: *runtime-version no-autodownload: true + org.freedesktop.Platform.GL32: directory: lib/i386-linux-gnu/GL - version: '20.08' + version: *gl-version + versions: *gl-versions subdirectories: true no-autodownload: true autodelete: false add-ld-path: lib - merge-dirs: vulkan/icd.d;glvnd/egl_vendor.d + merge-dirs: vulkan/icd.d;glvnd/egl_vendor.d;OpenCL/vendors;lib/dri;lib/d3d;vulkan/explicit_layer.d;vulkan/implicit_layer.d download-if: active-gl-driver enable-if: active-gl-driver + sdk-extensions: - org.freedesktop.Sdk.Compat.i386 - org.freedesktop.Sdk.Extension.toolchain-i386 + build-options: - prepend-pkg-config-path: "/app/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig" - ldflags: "-L/app/lib32" - append-path: "/usr/lib/sdk/toolchain-i386/bin" + prepend-pkg-config-path: /app/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig + ldflags: -L/app/lib32 + prepend-path: /usr/lib/sdk/toolchain-i386/bin env: CC: i686-unknown-linux-gnu-gcc CXX: i686-unknown-linux-gnu-g++ - libdir: "/app/lib32" + libdir: /app/lib32 + cleanup: - "/include" + modules: -- name: ld-i386 + +- name: platform-bootstrap buildsystem: simple build-commands: - - mkdir -p /app/lib/i386-linux-gnu /app/lib/debug/lib/i386-linux-gnu - - install -Dm644 -t /app/etc ld.so.conf + - | + set -e + mkdir -p /app/bin + mkdir -p /app/lib/i386-linux-gnu + mkdir -p /app/lib/debug/lib/i386-linux-gnu + mkdir -p /app/lib/i386-linux-gnu/GL + cp /usr/bin/addr2line /app/bin/ + cp /usr/lib/x86_64-linux-gnu/libbfd-*.so /app/lib/ + install -Dm644 -t /app/etc ld.so.conf + mkdir -p /app/links/lib + ln -srv /app/lib /app/links/lib/x86_64-linux-gnu + ln -srv /app/lib32 /app/links/lib/i386-linux-gnu sources: - - type: shell - commands: - - echo "/app/lib32" > ld.so.conf + - type: dir + path: .flatpak + - name: game buildsystem: simple build-commands: diff --git a/src_rebuild/Game/ASM/rnc_2.c b/src_rebuild/Game/ASM/rnc_2.c index 72459ba92..e5a8bfd82 100644 --- a/src_rebuild/Game/ASM/rnc_2.c +++ b/src_rebuild/Game/ASM/rnc_2.c @@ -28,7 +28,7 @@ struct RNCheader */ /*____________________________________________________________________________*/ -short testRNC(unsigned long firstLong) +short testRNC(unsigned int firstLong) { int method = 0; method = (firstLong & 0xFF000000) >> 24; //get low byte @@ -113,8 +113,8 @@ unsigned short get_offset(unsigned char** byteStreamPtr) /*____________________________________________________________________________*/ //RNC2 unpack -int RNCunpack2(unsigned char* packed, unsigned long srcSize, - unsigned char* unpacked, unsigned long dstSize) +int RNCunpack2(unsigned char* packed, unsigned int srcSize, + unsigned char* unpacked, unsigned int dstSize) { unsigned char* src = packed; unsigned char* dst = unpacked; diff --git a/src_rebuild/Game/ASM/rndrasm.c b/src_rebuild/Game/ASM/rndrasm.c index 0bb1c7598..ae1cd7ba5 100644 --- a/src_rebuild/Game/ASM/rndrasm.c +++ b/src_rebuild/Game/ASM/rndrasm.c @@ -2,7 +2,11 @@ #include "C/camera.h" #include "C/draw.h" -extern MATRIX frustrum_matrix; +#ifdef PSX +#pragma GCC optimization ("O3") +#endif + +#define FRUSTUM_THRESHOLD (-80) // [D] [T] void SetCameraVector(void) @@ -32,8 +36,7 @@ void Apply_Inv_CameraMatrix(VECTOR* v) // [D] [T] int Apply_InvCameraMatrixSetTrans(VECTOR_NOPAD* pos) { - VECTOR vfc; - VECTOR vec; + VECTOR vfc, vec; SVECTOR local; gte_stfc(&vfc); @@ -63,8 +66,7 @@ int Apply_InvCameraMatrixSetTrans(VECTOR_NOPAD* pos) // [D] [T] int Apply_InvCameraMatrixAndSetMatrix(VECTOR_NOPAD* pos, MATRIX2* mtx) { - VECTOR vfc; - VECTOR vec; + VECTOR vfc, vec; SVECTOR local; gte_stfc(&vfc); @@ -97,8 +99,9 @@ int Apply_InvCameraMatrixAndSetMatrix(VECTOR_NOPAD* pos, MATRIX2* mtx) // [D] [T] int FrustrumCheck16(PACKED_CELL_OBJECT* pcop, int bounding_sphere) { - VECTOR result; + VECTOR_NOPAD result; SVECTOR local; + int ang; VecSubtract(&local, &pcop->pos, &camera_position); gte_ldsv(&local); @@ -106,10 +109,12 @@ int FrustrumCheck16(PACKED_CELL_OBJECT* pcop, int bounding_sphere) gte_stlvnl(&result); - int ang = frustrum_matrix.t[0] - bounding_sphere; + ang = FRUSTUM_THRESHOLD - bounding_sphere; - if (ang <= result.vx && ang <= result.vy && ang <= result.vz) + if (ang <= result.vx && ang <= result.vy && ang <= result.vz) + { return 0; + } return -1; } @@ -117,8 +122,9 @@ int FrustrumCheck16(PACKED_CELL_OBJECT* pcop, int bounding_sphere) // [D] [T] int FrustrumCheck(VECTOR* pos, int bounding_sphere) { - VECTOR result; + VECTOR_NOPAD result; SVECTOR local; + int ang; VecSubtract(&local, pos, &camera_position); gte_ldsv(&local); @@ -126,10 +132,12 @@ int FrustrumCheck(VECTOR* pos, int bounding_sphere) gte_stlvnl(&result); - int ang = frustrum_matrix.t[0] - bounding_sphere; + ang = FRUSTUM_THRESHOLD - bounding_sphere; - if (ang <= result.vx && ang <= result.vy && ang <= result.vz) + if (ang <= result.vx && ang <= result.vy && ang <= result.vz) + { return 0; + } return -1; } diff --git a/src_rebuild/Game/C/bcollide.c b/src_rebuild/Game/C/bcollide.c index 5a2d90012..3ca46c5e8 100644 --- a/src_rebuild/Game/C/bcollide.c +++ b/src_rebuild/Game/C/bcollide.c @@ -13,6 +13,7 @@ #include "camera.h" #include "objanim.h" #include "system.h" +#include "cutscene.h" extern int gCameraBoxOverlap; @@ -45,8 +46,8 @@ int bcollided2d(CDATA2D *body, int* boxOverlap) } // hmmm, why? - as = RSIN(dtheta & 0x7ff); // rcossin_tbl[(dtheta & 0x7ff) * 2]; - ac = RSIN(dtheta + 1024 & 0x7ff); // rcossin_tbl[(dtheta + 1024 & 0x7ff) * 2]; + as = RSIN(dtheta & 2047); // rcossin_tbl[(dtheta & 0x7ff) * 2]; + ac = RSIN(dtheta + 1024 & 2047); // rcossin_tbl[(dtheta + 1024 & 0x7ff) * 2]; delta.vx = body[0].x.vx - body[1].x.vx; delta.vz = body[0].x.vz - body[1].x.vz; @@ -547,29 +548,19 @@ void DamageCar(CAR_DATA *cp, CDATA2D *cd, CRET2D *collisionResult, int strikeVel // [D] [T] int CarBuildingCollision(CAR_DATA *cp, BUILDING_BOX *building, CELL_OBJECT *cop, int flags) { - int temp; int strikeVel; - int boxDiffY; + int boxDiffY, buildingHeightY; int collided; - short scale; - int chan; int player_id; - SMASHABLE_OBJECT *match; + SMASHABLE_OBJECT* match; SMASHABLE_OBJECT* sip; CAR_COSMETICS* car_cos; MODEL *model; - VECTOR tempwhere; + VECTOR tempwhere, velocity; SVECTOR boxDisp; - VECTOR velocity; - LONGVECTOR4 pointVel; - LONGVECTOR4 reaction; - LONGVECTOR4 lever; - VECTOR LeafPosition; - VECTOR lamp_velocity; + LONGVECTOR4 pointVel, reaction, lever; int debris_colour; - int displacement; - int denom; - int buildingHeightY; + int displacement, denom; #if 0 //def PSX CDATA2D* cd = (CDATA2D*)(u_char*)getScratchAddr(0); @@ -583,423 +574,408 @@ int CarBuildingCollision(CAR_DATA *cp, BUILDING_BOX *building, CELL_OBJECT *cop, #endif model = modelpointers[cop->type]; - player_id = GetPlayerId(cp); - - cd[0].isCameraOrTanner = (cp->controlType == CONTROL_TYPE_TANNERCOLLIDER || cp->controlType == CONTROL_TYPE_CAMERACOLLIDER); - - if (cp->controlType == CONTROL_TYPE_TANNERCOLLIDER) - cd[0].isCameraOrTanner += 2; - - cd[1].isCameraOrTanner = (flags & CollisionCheckFlag_MightBeABarrier) == 0; boxDiffY = cp->hd.oBox.location.vy + building->pos.vy; boxDiffY = ABS(boxDiffY); - collided = 0; - - car_cos = cp->ap.carCos; - // [A] Boat Jump: make player's life easier getting out if (cop->type == 1246 && gCurrentMissionNumber == 35) buildingHeightY = building->height / 5; else buildingHeightY = building->height >> 1; - if (boxDiffY <= buildingHeightY + (cp->hd.oBox.length[1] >> 1) && (cop->pos.vx != OBJECT_SMASHED_MARK) && (model->shape_flags & SHAPE_FLAG_NOCOLLIDE) == 0) + if (boxDiffY > buildingHeightY + (cp->hd.oBox.length[1] >> 1) || + (cop->pos.vx == OBJECT_SMASHED_MARK) || + (model->shape_flags & SHAPE_FLAG_NOCOLLIDE)) { - tempwhere.vx = cp->hd.where.t[0]; - tempwhere.vz = cp->hd.where.t[2]; + return 0; + } + + collided = 0; + car_cos = cp->ap.carCos; - debris_colour = GetDebrisColour(cp); + player_id = GetPlayerId(cp); - cd[0].theta = cp->hd.direction; + cd[0].isCameraOrTanner = (cp->controlType == CONTROL_TYPE_TANNERCOLLIDER || cp->controlType == CONTROL_TYPE_CAMERACOLLIDER); - if (cp->controlType == CONTROL_TYPE_TANNERCOLLIDER) - { - cd[0].x.vx = cp->hd.where.t[0]; - cd[0].x.vy = cp->hd.where.t[1]; - cd[0].x.vz = cp->hd.where.t[2]; - - cd[0].vel.vx = FIXEDH(cp->st.n.linearVelocity[0]); - cd[0].vel.vz = FIXEDH(cp->st.n.linearVelocity[2]); + if (cp->controlType == CONTROL_TYPE_TANNERCOLLIDER) + cd[0].isCameraOrTanner += 2; - cp->hd.where.t[0] += cd[0].vel.vx; - cp->hd.where.t[2] += cd[0].vel.vz; + cd[1].isCameraOrTanner = (flags & CollisionCheckFlag_MightBeABarrier) == 0; - cd[0].length[0] = 90; - cd[0].length[1] = 90; - } - else if (cp->controlType == CONTROL_TYPE_CAMERACOLLIDER) - { - cd[0].x.vx = cp->hd.where.t[0]; - cd[0].x.vy = cp->hd.where.t[1]; - cd[0].x.vz = cp->hd.where.t[2]; + if (cp->controlType == CONTROL_TYPE_TANNERCOLLIDER) + { + cd[0].x.vx = cp->hd.where.t[0]; + cd[0].x.vy = cp->hd.where.t[1]; + cd[0].x.vz = cp->hd.where.t[2]; - cd[0].vel.vx = 0; - cd[0].vel.vz = 0; - cd[0].length[1] = 5; - cd[0].length[0] = gCameraDistance / 2; - } - else - { - gte_SetRotMatrix(&cp->hd.where); - gte_SetTransMatrix(&cp->hd.where); - - boxDisp.vx = -car_cos->cog.vx; - boxDisp.vy = -car_cos->cog.vy; - boxDisp.vz = -car_cos->cog.vz; + cd[0].vel.vx = FIXEDH(cp->st.n.linearVelocity[0]); + cd[0].vel.vz = FIXEDH(cp->st.n.linearVelocity[2]); - gte_ldv0(&boxDisp); + cd[0].length[0] = 90; + cd[0].length[1] = 90; + } + else if (cp->controlType == CONTROL_TYPE_CAMERACOLLIDER) + { + cd[0].x.vx = cp->hd.where.t[0]; + cd[0].x.vy = cp->hd.where.t[1]; + cd[0].x.vz = cp->hd.where.t[2]; + + cd[0].vel.vx = 0; + cd[0].vel.vz = 0; + cd[0].length[1] = 5; + cd[0].length[0] = gCameraDistance / 2; + } + else + { + gte_SetRotMatrix(&cp->hd.where); + gte_SetTransMatrix(&cp->hd.where); - gte_rtv0tr(); + boxDisp.vx = -car_cos->cog.vx; + boxDisp.vy = -car_cos->cog.vy; + boxDisp.vz = -car_cos->cog.vz; - gte_stlvnl(&cd[0].x); + gte_ldv0(&boxDisp); + gte_rtv0tr(); + gte_stlvnl(&cd[0].x); - cd[0].vel.vx = FIXEDH(cp->st.n.linearVelocity[0]); - cd[0].vel.vz = FIXEDH(cp->st.n.linearVelocity[2]); + cd[0].vel.vx = FIXEDH(cp->st.n.linearVelocity[0]); + cd[0].vel.vz = FIXEDH(cp->st.n.linearVelocity[2]); - cp->hd.where.t[0] += cd[0].vel.vx; - cp->hd.where.t[2] += cd[0].vel.vz; + cd[0].length[0] = car_cos->colBox.vz + 15; + cd[0].length[1] = car_cos->colBox.vx + 15; - cd[0].length[0] = car_cos->colBox.vz + 15; - cd[0].length[1] = car_cos->colBox.vx + 15; + if (handlingType[cp->hndType].fourWheelDrive == 1 || cp->hndType == 5) + cd[0].length[1] = (cd[0].length[1] * 13) / 16; + } - if (handlingType[cp->hndType].fourWheelDrive == 1 || cp->hndType == 5) - cd[0].length[1] = (cd[0].length[1] * 13) / 16; - } + cd[0].theta = cp->hd.direction; + cd[0].avel = FIXEDH(cp->st.n.angularVelocity[1]) * 5 >> 5; - cd[0].avel = FIXEDH(cp->st.n.angularVelocity[1]) * 5 >> 5; + tempwhere.vx = cp->hd.where.t[0]; + tempwhere.vz = cp->hd.where.t[2]; - cd[1].x.vx = cp->hd.where.t[0] + (((building->pos.vx - cp->hd.where.t[0]) << 0x10) >> 0x10); - cd[1].x.vz = cp->hd.where.t[2] + (((building->pos.vz - cp->hd.where.t[2]) << 0x10) >> 0x10); + cp->hd.where.t[0] += cd[0].vel.vx; + cp->hd.where.t[2] += cd[0].vel.vz; - cd[1].theta = building->theta; - cd[1].length[0] = building->xsize; - cd[1].length[1] = building->zsize; - cd[1].vel.vx = 0; - cd[1].vel.vz = 0; - cd[1].avel = 0; + cd[1].x.vx = cp->hd.where.t[0] + (short)(building->pos.vx - cp->hd.where.t[0]); + cd[1].x.vz = cp->hd.where.t[2] + (short)(building->pos.vz - cp->hd.where.t[2]); - if (cp->controlType == CONTROL_TYPE_CAMERACOLLIDER) - { - collided = bcollided2d(cd, &gCameraBoxOverlap); - } - else - { - collided = bcollided2d(cd); + cd[1].theta = building->theta; + cd[1].length[0] = building->xsize; + cd[1].length[1] = building->zsize; + cd[1].vel.vx = 0; + cd[1].vel.vz = 0; + cd[1].avel = 0; + + collided = bcollided2d(cd, cp->controlType == CONTROL_TYPE_CAMERACOLLIDER ? &gCameraBoxOverlap : 0); #if defined(COLLISION_DEBUG) && !defined(PSX) - extern int gShowCollisionDebug; - if (gShowCollisionDebug == 1) - { - extern void Debug_AddLine(VECTOR & pointA, VECTOR & pointB, CVECTOR & color); - extern void Debug_AddLineOfs(VECTOR & pointA, VECTOR & pointB, VECTOR & ofs, CVECTOR & color); + extern int gShowCollisionDebug; + if (gShowCollisionDebug == 1) + { + extern void Debug_AddLine(VECTOR & pointA, VECTOR & pointB, CVECTOR & color); + extern void Debug_AddLineOfs(VECTOR & pointA, VECTOR & pointB, VECTOR & ofs, CVECTOR & color); - CVECTOR bbcv = { 0, 0, 250 }; - CVECTOR rrcv = { 250, 0, 0 }; - CVECTOR yycv = { 250, 250, 0 }; + CVECTOR bbcv = { 0, 0, 250 }; + CVECTOR rrcv = { 250, 0, 0 }; + CVECTOR yycv = { 250, 250, 0 }; - // show both box axes - { - VECTOR _zero = { 0 }; - VECTOR b1p = cd[0].x; - VECTOR b2p = cd[1].x; - b2p.vy = b1p.vy; + // show both box axes + { + VECTOR _zero = { 0 }; + VECTOR b1p = cd[0].x; + VECTOR b2p = cd[1].x; + b2p.vy = b1p.vy; - // show position to position - //Debug_AddLine(b1p1, b2p1, yycv); + // show position to position + //Debug_AddLine(b1p1, b2p1, yycv); - VECTOR b1ax[2] = { {0} , {0} }; - b1ax[0].vx = FIXEDH(cd[0].axis[0].vx * cd[0].length[0]); - b1ax[0].vz = FIXEDH(cd[0].axis[0].vz * cd[0].length[0]); - b1ax[1].vx = FIXEDH(cd[0].axis[1].vx * cd[0].length[1]); - b1ax[1].vz = FIXEDH(cd[0].axis[1].vz * cd[0].length[1]); + VECTOR b1ax[2] = { {0} , {0} }; + b1ax[0].vx = FIXEDH(cd[0].axis[0].vx * cd[0].length[0]); + b1ax[0].vz = FIXEDH(cd[0].axis[0].vz * cd[0].length[0]); + b1ax[1].vx = FIXEDH(cd[0].axis[1].vx * cd[0].length[1]); + b1ax[1].vz = FIXEDH(cd[0].axis[1].vz * cd[0].length[1]); - // show axis of body 1 - Debug_AddLineOfs(_zero, b1ax[0], b1p, rrcv); - Debug_AddLineOfs(_zero, b1ax[1], b1p, yycv); + // show axis of body 1 + Debug_AddLineOfs(_zero, b1ax[0], b1p, rrcv); + Debug_AddLineOfs(_zero, b1ax[1], b1p, yycv); - // display 2D box 1 - { - int h = b1ax[0].vy; - VECTOR box_points[4] = { - {b1ax[0].vx - b1ax[1].vx, h, b1ax[0].vz - b1ax[1].vz, 0}, // front left - {b1ax[0].vx + b1ax[1].vx, h, b1ax[0].vz + b1ax[1].vz, 0}, // front right - - {-b1ax[0].vx + b1ax[1].vx, h, -b1ax[0].vz + b1ax[1].vz, 0}, // back right - {-b1ax[0].vx - b1ax[1].vx, h, -b1ax[0].vz - b1ax[1].vz, 0} // back left - }; - - Debug_AddLineOfs(box_points[0], box_points[1], b1p, bbcv); - Debug_AddLineOfs(box_points[1], box_points[2], b1p, bbcv); - Debug_AddLineOfs(box_points[2], box_points[3], b1p, bbcv); - Debug_AddLineOfs(box_points[3], box_points[0], b1p, bbcv); - } + // display 2D box 1 + { + int h = b1ax[0].vy; + VECTOR box_points[4] = { + {b1ax[0].vx - b1ax[1].vx, h, b1ax[0].vz - b1ax[1].vz, 0}, // front left + {b1ax[0].vx + b1ax[1].vx, h, b1ax[0].vz + b1ax[1].vz, 0}, // front right + + {-b1ax[0].vx + b1ax[1].vx, h, -b1ax[0].vz + b1ax[1].vz, 0}, // back right + {-b1ax[0].vx - b1ax[1].vx, h, -b1ax[0].vz - b1ax[1].vz, 0} // back left + }; + + Debug_AddLineOfs(box_points[0], box_points[1], b1p, bbcv); + Debug_AddLineOfs(box_points[1], box_points[2], b1p, bbcv); + Debug_AddLineOfs(box_points[2], box_points[3], b1p, bbcv); + Debug_AddLineOfs(box_points[3], box_points[0], b1p, bbcv); + } - VECTOR b2ax[2] = { {0} , {0} }; - b2ax[0].vx += FIXEDH(cd[1].axis[0].vx * cd[1].length[0]); - b2ax[0].vz += FIXEDH(cd[1].axis[0].vz * cd[1].length[0]); - b2ax[1].vx += FIXEDH(cd[1].axis[1].vx * cd[1].length[1]); - b2ax[1].vz += FIXEDH(cd[1].axis[1].vz * cd[1].length[1]); + VECTOR b2ax[2] = { {0} , {0} }; + b2ax[0].vx += FIXEDH(cd[1].axis[0].vx * cd[1].length[0]); + b2ax[0].vz += FIXEDH(cd[1].axis[0].vz * cd[1].length[0]); + b2ax[1].vx += FIXEDH(cd[1].axis[1].vx * cd[1].length[1]); + b2ax[1].vz += FIXEDH(cd[1].axis[1].vz * cd[1].length[1]); - // show axis of body 2 - Debug_AddLineOfs(_zero, b2ax[0], b2p, rrcv); - Debug_AddLineOfs(_zero, b2ax[1], b2p, yycv); + // show axis of body 2 + Debug_AddLineOfs(_zero, b2ax[0], b2p, rrcv); + Debug_AddLineOfs(_zero, b2ax[1], b2p, yycv); - CVECTOR& collColor = collided ? rrcv : yycv; + CVECTOR& collColor = collided ? rrcv : yycv; - // display 2D box 2 - { - int h = b2ax[0].vy; - VECTOR box_points[4] = { - {b2ax[0].vx - b2ax[1].vx, h, b2ax[0].vz - b2ax[1].vz, 0}, // front left - {b2ax[0].vx + b2ax[1].vx, h, b2ax[0].vz + b2ax[1].vz, 0}, // front right - - {-b2ax[0].vx + b2ax[1].vx, h, -b2ax[0].vz + b2ax[1].vz, 0}, // back right - {-b2ax[0].vx - b2ax[1].vx, h, -b2ax[0].vz - b2ax[1].vz, 0} // back left - }; - - Debug_AddLineOfs(box_points[0], box_points[1], b2p, collColor); - Debug_AddLineOfs(box_points[1], box_points[2], b2p, collColor); - Debug_AddLineOfs(box_points[2], box_points[3], b2p, collColor); - Debug_AddLineOfs(box_points[3], box_points[0], b2p, collColor); - } - } + // display 2D box 2 + { + int h = b2ax[0].vy; + VECTOR box_points[4] = { + {b2ax[0].vx - b2ax[1].vx, h, b2ax[0].vz - b2ax[1].vz, 0}, // front left + {b2ax[0].vx + b2ax[1].vx, h, b2ax[0].vz + b2ax[1].vz, 0}, // front right + + {-b2ax[0].vx + b2ax[1].vx, h, -b2ax[0].vz + b2ax[1].vz, 0}, // back right + {-b2ax[0].vx - b2ax[1].vx, h, -b2ax[0].vz - b2ax[1].vz, 0} // back left + }; + + Debug_AddLineOfs(box_points[0], box_points[1], b2p, collColor); + Debug_AddLineOfs(box_points[1], box_points[2], b2p, collColor); + Debug_AddLineOfs(box_points[2], box_points[3], b2p, collColor); + Debug_AddLineOfs(box_points[3], box_points[0], b2p, collColor); } + } + } #endif - if (collided) - { - bFindCollisionTime(cd, &collisionResult); - bFindCollisionPoint(cd, &collisionResult); + if (cp->controlType != CONTROL_TYPE_CAMERACOLLIDER) + { + if (collided) + { + bFindCollisionTime(cd, &collisionResult); + bFindCollisionPoint(cd, &collisionResult); #if defined(COLLISION_DEBUG) && !defined(PSX) - extern int gShowCollisionDebug; - if(gShowCollisionDebug == 1) - { - extern void Debug_AddLine(VECTOR& pointA, VECTOR& pointB, CVECTOR& color); - extern void Debug_AddLineOfs(VECTOR& pointA, VECTOR& pointB, VECTOR& ofs, CVECTOR& color); + extern int gShowCollisionDebug; + if(gShowCollisionDebug == 1) + { + extern void Debug_AddLine(VECTOR& pointA, VECTOR& pointB, CVECTOR& color); + extern void Debug_AddLineOfs(VECTOR& pointA, VECTOR& pointB, VECTOR& ofs, CVECTOR& color); - CVECTOR bbcv = { 0, 0, 250 }; - CVECTOR rrcv = { 250, 0, 0 }; - CVECTOR yycv = { 250, 250, 0 }; + CVECTOR bbcv = { 0, 0, 250 }; + CVECTOR rrcv = { 250, 0, 0 }; + CVECTOR yycv = { 250, 250, 0 }; - // show collision point and normal - { + // show collision point and normal + { - VECTOR pb = collisionResult.hit; - pb.vy += 16; + VECTOR pb = collisionResult.hit; + pb.vy += 16; - // display collision point - Debug_AddLine(collisionResult.hit, pb, rrcv); + // display collision point + Debug_AddLine(collisionResult.hit, pb, rrcv); - VECTOR nb = collisionResult.hit; - nb.vx += collisionResult.surfNormal.vx / 16; - nb.vy += collisionResult.surfNormal.vy / 16; - nb.vz += collisionResult.surfNormal.vz / 16; + VECTOR nb = collisionResult.hit; + nb.vx += collisionResult.surfNormal.vx / 16; + nb.vy += collisionResult.surfNormal.vy / 16; + nb.vz += collisionResult.surfNormal.vz / 16; - // show collision normal - Debug_AddLine(collisionResult.hit, nb, bbcv); - } + // show collision normal + Debug_AddLine(collisionResult.hit, nb, bbcv); } + } #endif - collisionResult.surfNormal.vx = -collisionResult.surfNormal.vx; - collisionResult.surfNormal.vy = 0; - collisionResult.surfNormal.vz = -collisionResult.surfNormal.vz; + collisionResult.surfNormal.vx = -collisionResult.surfNormal.vx; + collisionResult.surfNormal.vy = 0; + collisionResult.surfNormal.vz = -collisionResult.surfNormal.vz; - collisionResult.hit.vy = cp->hd.where.t[1] + 41; + collisionResult.hit.vy = cp->hd.where.t[1] + 41; - // perform error correction + // perform error correction + if((model->flags2 & MODEL_FLAG_SMASHABLE) == 0 || gInGameCutsceneActive == 0 || cd[0].isCameraOrTanner) + { cp->hd.where.t[0] += FIXEDH(collisionResult.penetration * collisionResult.surfNormal.vx); cp->hd.where.t[2] += FIXEDH(collisionResult.penetration * collisionResult.surfNormal.vz); + } + + lever[0] = collisionResult.hit.vx - cp->hd.where.t[0]; + lever[1] = collisionResult.hit.vy - cp->hd.where.t[1]; + lever[2] = collisionResult.hit.vz - cp->hd.where.t[2]; + + pointVel[0] = FIXEDH(cp->st.n.angularVelocity[1] * lever[2] - cp->st.n.angularVelocity[2] * lever[1]) + cp->st.n.linearVelocity[0]; + pointVel[1] = FIXEDH(cp->st.n.angularVelocity[2] * lever[0] - cp->st.n.angularVelocity[0] * lever[2]) + cp->st.n.linearVelocity[1]; + pointVel[2] = FIXEDH(cp->st.n.angularVelocity[0] * lever[1] - cp->st.n.angularVelocity[1] * lever[0]) + cp->st.n.linearVelocity[2]; + + if (flags & CollisionCheckFlag_IsVegasMovingTrain) // [A] Vegas train velocity - added here + { + pointVel[2] += 700000; + } - lever[0] = collisionResult.hit.vx - cp->hd.where.t[0]; - lever[1] = collisionResult.hit.vy - cp->hd.where.t[1]; - lever[2] = collisionResult.hit.vz - cp->hd.where.t[2]; - - pointVel[0] = FIXEDH(cp->st.n.angularVelocity[1] * lever[2] - cp->st.n.angularVelocity[2] * lever[1]) + cp->st.n.linearVelocity[0]; - pointVel[1] = FIXEDH(cp->st.n.angularVelocity[2] * lever[0] - cp->st.n.angularVelocity[0] * lever[2]) + cp->st.n.linearVelocity[1]; - pointVel[2] = FIXEDH(cp->st.n.angularVelocity[0] * lever[1] - cp->st.n.angularVelocity[1] * lever[0]) + cp->st.n.linearVelocity[2]; + strikeVel = -((pointVel[0] / 256) * (collisionResult.surfNormal.vx / 16) + + (pointVel[1] / 256) * (collisionResult.surfNormal.vy / 16) + + (pointVel[2] / 256) * (collisionResult.surfNormal.vz / 16)); - if (flags & CollisionCheckFlag_IsVegasMovingTrain) // [A] Vegas train velocity - added here + if (strikeVel > 0) + { + if (cp->controlType == CONTROL_TYPE_PLAYER) { - pointVel[2] += 700000; + short scale; + + if (strikeVel < 32) + scale = ((strikeVel << 23) >> 16); + else + scale = 4096; + + if (model->flags2 & MODEL_FLAG_SMASHABLE) + NoteFelony(&felonyData, 7, scale); + else + NoteFelony(&felonyData, 6, scale); } - strikeVel = -((pointVel[0] / 256) * (collisionResult.surfNormal.vx / 16) + - (pointVel[1] / 256) * (collisionResult.surfNormal.vy / 16) + - (pointVel[2] / 256) * (collisionResult.surfNormal.vz / 16)); + collisionResult.hit.vy = -collisionResult.hit.vy; - if (strikeVel > 0) - { - if (cp->controlType == CONTROL_TYPE_PLAYER) - { - if (strikeVel < 32) - scale = ((strikeVel << 23) >> 16); - else - scale = 4096; - - if (model->flags2 & MODEL_FLAG_SMASHABLE) - NoteFelony(&felonyData, 7, scale); - else - NoteFelony(&felonyData, 6, scale); - } + velocity.vx = cp->st.n.linearVelocity[0] / ONE; + velocity.vy = -17; + velocity.vz = cp->st.n.linearVelocity[2] / ONE; - collisionResult.hit.vy = -collisionResult.hit.vy; + debris_colour = GetDebrisColour(cp); - velocity.vx = cp->st.n.linearVelocity[0] / ONE; - velocity.vy = -17; - velocity.vz = cp->st.n.linearVelocity[2] / ONE; + if (model->flags2 & MODEL_FLAG_SMASHABLE) + { + // smash object + damage_object(cop, &velocity); - if (model->flags2 & MODEL_FLAG_SMASHABLE) + // smash object + if ((model->shape_flags & SHAPE_FLAG_TRANS) == 0) { - // smash object - damage_object(cop, &velocity); + int chan; - // smash object - if ((model->shape_flags & SHAPE_FLAG_TRANS) == 0) - { - sip = smashable; - match = sip; + sip = smashable; + match = sip; - while (sip->name != NULL) + while (sip->name != NULL) + { + if (sip->modelIdx == cop->type) { - if (sip->modelIdx == cop->type) - { - match = sip; - break; - } - sip++; + match = sip; + break; } + sip++; + } - chan = GetFreeChannel(); + chan = GetFreeChannel(); - if (NumPlayers > 1 && NoPlayerControl == 0) - SetPlayerOwnsChannel(chan, player_id); + if (NumPlayers > 1 && NoPlayerControl == 0) + SetPlayerOwnsChannel(chan, player_id); - Start3DSoundVolPitch(chan, SOUND_BANK_SFX, match->sound, - collisionResult.hit.vx, -collisionResult.hit.vy, collisionResult.hit.vz, - match->volume, match->pitch + (((velocity.vx ^ velocity.vz) * (collisionResult.hit.vx ^ collisionResult.hit.vz) & 0x3ff) - 0x200)); - } + Start3DSoundVolPitch(chan, SOUND_BANK_SFX, match->sound, + collisionResult.hit.vx, -collisionResult.hit.vy, collisionResult.hit.vz, + match->volume, match->pitch + (((velocity.vx ^ velocity.vz) * (collisionResult.hit.vx ^ collisionResult.hit.vz) & 1023) - 512)); + } - cp->hd.where.t[0] = tempwhere.vx; - cp->hd.where.t[2] = tempwhere.vz; + cp->hd.where.t[0] = tempwhere.vx; + cp->hd.where.t[2] = tempwhere.vz; - collisionResult.hit.vy += 30; + collisionResult.hit.vy += 30; - Setup_Sparks(&collisionResult.hit, &velocity, 10, 0); - Setup_Debris(&collisionResult.hit, &velocity, 5, 0); - Setup_Debris(&collisionResult.hit, &velocity, 5, debris_colour << 0x10); + Setup_Sparks(&collisionResult.hit, &velocity, 10, 0); + Setup_Debris(&collisionResult.hit, &velocity, 5, 0); + Setup_Debris(&collisionResult.hit, &velocity, 5, debris_colour << 0x10); - if (cp->controlType == CONTROL_TYPE_PLAYER) - SetPadVibration(*cp->ai.padid, 3); + if (cp->controlType == CONTROL_TYPE_PLAYER) + SetPadVibration(*cp->ai.padid, 3); - return 0; - } + return 0; + } - // add leaves - if (strikeVel > 0x3600 && cp->hd.wheel_speed + 16000U > 32000) + // add leaves + if (strikeVel > 0x3600 && cp->hd.wheel_speed + 16000U > 32000) + { + if (model->flags2 & MODEL_FLAG_TREE) { - if (model->flags2 & MODEL_FLAG_TREE) - { - LeafPosition.vx = collisionResult.hit.vx; - LeafPosition.vy = -((rand() & 0xfe) + 600) - collisionResult.hit.vy; - LeafPosition.vz = collisionResult.hit.vz; + VECTOR LeafPosition; + LeafPosition.vx = collisionResult.hit.vx; + LeafPosition.vy = -((rand() & 0xfe) + 600) - collisionResult.hit.vy; + LeafPosition.vz = collisionResult.hit.vz; - AddLeaf(&LeafPosition, 3, 1); - } - else + AddLeaf(&LeafPosition, 3, 1); + } + else + { + if (gNight && (model->flags2 & MODEL_FLAG_LAMP)) { - if (gNight && (model->flags2 & MODEL_FLAG_LAMP)) + if (damage_lamp(cop)) { - if (damage_lamp(cop)) - { - ClearMem((char*)&lamp_velocity, sizeof(lamp_velocity)); - - collisionResult.hit.vy -= 730; - Setup_Sparks(&collisionResult.hit, &lamp_velocity, 0x14, 0); - collisionResult.hit.vy += 730; - } + VECTOR lamp_velocity; + lamp_velocity.vx = 0; + lamp_velocity.vy = 16; + lamp_velocity.vz = 0; + + collisionResult.hit.vy -= 730; + Setup_Sparks(&collisionResult.hit, &lamp_velocity, 20, 0); + collisionResult.hit.vy += 730; } - - velocity.vy -= 20; - collisionResult.hit.vy += 30; - - Setup_Sparks(&collisionResult.hit, &velocity, 4, 0); - - collisionResult.hit.vy -= 30; - velocity.vy += 20; } - if (strikeVel > 0x1b000) - { - Setup_Debris(&collisionResult.hit, &velocity, 6, debris_colour << 0x10); - - if(cp->controlType == CONTROL_TYPE_PLAYER) - SetPadVibration(*cp->ai.padid, 1); - } - } - - DamageCar(cp, cd, &collisionResult, strikeVel); - - displacement = FIXEDH(lever[0] * collisionResult.surfNormal.vx + lever[1] * collisionResult.surfNormal.vy + lever[2] * collisionResult.surfNormal.vz); - displacement = FIXEDH(((lever[0] * lever[0] + lever[2] * lever[2]) - displacement * displacement) * car_cos->twistRateY) + 4096; - - if (strikeVel < 0x7f001) - denom = (strikeVel * 4096) / displacement; - else - denom = (strikeVel / displacement) * 4096; - - denom /= 64; + velocity.vy -= 20; + collisionResult.hit.vy += 30; - reaction[0] = denom * (collisionResult.surfNormal.vx / 64); - reaction[1] = denom * (collisionResult.surfNormal.vy / 64); - reaction[2] = denom * (collisionResult.surfNormal.vz / 64); + Setup_Sparks(&collisionResult.hit, &velocity, 4, 0); - cp->hd.aacc[1] += FIXEDH(lever[2] * reaction[0]) - FIXEDH(lever[0] * reaction[2]); + collisionResult.hit.vy -= 30; + velocity.vy += 20; + } - // angular impulse calculation and modifiers - if (cp->controlType != CONTROL_TYPE_LEAD_AI) + if (strikeVel > 0x1b000) { - temp = FIXEDH(lever[1] * reaction[2]); - - if (cp->controlType == CONTROL_TYPE_PURSUER_AI) - temp >>= 1; + Setup_Debris(&collisionResult.hit, &velocity, 6, debris_colour << 0x10); - cp->hd.aacc[0] += temp; + if(cp->controlType == CONTROL_TYPE_PLAYER) + SetPadVibration(*cp->ai.padid, 1); + } + } - temp = FIXEDH(lever[2] * reaction[1]); + DamageCar(cp, cd, &collisionResult, strikeVel); - if (cp->controlType == CONTROL_TYPE_PURSUER_AI) - temp >>= 1; - - cp->hd.aacc[0] -= temp; + displacement = FIXEDH(lever[0] * collisionResult.surfNormal.vx + lever[1] * collisionResult.surfNormal.vy + lever[2] * collisionResult.surfNormal.vz); + displacement = FIXEDH(((lever[0] * lever[0] + lever[2] * lever[2]) - displacement * displacement) * car_cos->twistRateY) + 4096; - temp = FIXEDH(lever[0] * reaction[1]); + if (strikeVel < 0x7f001) + denom = (strikeVel * 4096) / displacement; + else + denom = (strikeVel / displacement) * 4096; - if (cp->controlType == CONTROL_TYPE_PURSUER_AI) - temp >>= 1; + denom /= 64; - cp->hd.aacc[2] += temp; + reaction[0] = denom * (collisionResult.surfNormal.vx / 64); + reaction[1] = denom * (collisionResult.surfNormal.vy / 64); + reaction[2] = denom * (collisionResult.surfNormal.vz / 64); - temp = FIXEDH(lever[1] * reaction[0]); + cp->hd.aacc[1] += FIXEDH(lever[2] * reaction[0]) - FIXEDH(lever[0] * reaction[2]); - if (cp->controlType == CONTROL_TYPE_PURSUER_AI) - temp >>= 1; - - cp->hd.aacc[2] -= temp; + // angular impulse calculation and modifiers + if (cp->controlType != CONTROL_TYPE_LEAD_AI) + { + int reduction; + reduction = (cp->controlType == CONTROL_TYPE_PURSUER_AI); - cp->st.n.linearVelocity[1] += reaction[1]; - } + cp->hd.aacc[0] += FIXEDH(lever[1] * reaction[2]) >> reduction; + cp->hd.aacc[0] -= FIXEDH(lever[2] * reaction[1]) >> reduction; + cp->hd.aacc[2] += FIXEDH(lever[0] * reaction[1]) >> reduction; + cp->hd.aacc[2] -= FIXEDH(lever[1] * reaction[0]) >> reduction; - cp->st.n.linearVelocity[0] += reaction[0]; - cp->st.n.linearVelocity[2] += reaction[2]; + cp->st.n.linearVelocity[1] += reaction[1]; } - } - cp->hd.where.t[0] -= FIXEDH(cp->st.n.linearVelocity[0]); - cp->hd.where.t[2] -= FIXEDH(cp->st.n.linearVelocity[2]); + cp->st.n.linearVelocity[0] += reaction[0]; + cp->st.n.linearVelocity[2] += reaction[2]; + } } + + cp->hd.where.t[0] -= FIXEDH(cp->st.n.linearVelocity[0]); + cp->hd.where.t[2] -= FIXEDH(cp->st.n.linearVelocity[2]); } return collided; diff --git a/src_rebuild/Game/C/camera.c b/src_rebuild/Game/C/camera.c index 2dfc3a077..26012cebf 100644 --- a/src_rebuild/Game/C/camera.c +++ b/src_rebuild/Game/C/camera.c @@ -286,9 +286,7 @@ int CameraCollisionCheck(void) if (gCameraDistance > 0) { - ppco = GetFirstPackedCop(cellx, cellz, &ci, 0, cellLevel); - - while (ppco) + for (ppco = GetFirstPackedCop(cellx, cellz, &ci, 0, cellLevel); ppco; ppco = GetNextPackedCop(&ci)) { int type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10); @@ -349,7 +347,6 @@ int CameraCollisionCheck(void) } } } - ppco = GetNextPackedCop(&ci); } } count++; @@ -592,9 +589,9 @@ void PlaceCameraInCar(PLAYER *lp, int BumperCam) // [A] handle REDRIVER2 dedicated look back button if ((paddCamera & CAMERA_PAD_LOOK_BACK) == CAMERA_PAD_LOOK_BACK || (paddCamera & CAMERA_PAD_LOOK_BACK_DED)) - camera_angle.vy = 2048 - baseDir & 0xfff; + camera_angle.vy = 2048 - baseDir & 4095; else - camera_angle.vy = (lp->headPos >> 16) - baseDir & 0xfff; + camera_angle.vy = (lp->headPos >> 16) - baseDir & 4095; if (cp) { @@ -632,13 +629,18 @@ void PlaceCameraInCar(PLAYER *lp, int BumperCam) } else { + LPPEDESTRIAN pPlayerPed; + pPlayerPed = lp->pPed; + camera_angle.vx = -tannerLookAngle.vx; - // pedestrian camera is much simpler BuildWorldMatrix(); - viewer_position.vy += lp->pPed->head_pos - 25; - //viewer_position.vz += 45; + if (pPlayerPed) + { + // apply pedestrian bobbing + viewer_position.vy += pPlayerPed->head_pos - 25; + } angle = -baseDir; @@ -702,7 +704,7 @@ void PlaceCameraAtLocation(PLAYER* lp, int zoom) d = PointAtTarget(&lp->cameraPos, &temp, &camera_angle); - if (d > 16000) + if (d > VIEW_DRAW_DISTANCE) { lp->cameraView = 0; return; diff --git a/src_rebuild/Game/C/camera.h b/src_rebuild/Game/C/camera.h index bb40847f7..875dc8dca 100644 --- a/src_rebuild/Game/C/camera.h +++ b/src_rebuild/Game/C/camera.h @@ -3,6 +3,12 @@ #define CAMERA_COLLIDER_CARID (MAX_CARS+1) +#ifdef PSX +#define VIEW_DRAW_DISTANCE 16000 +#else +#define VIEW_DRAW_DISTANCE 22000 +#endif + extern VECTOR camera_position; extern char old_camera_change; extern char camera_change; diff --git a/src_rebuild/Game/C/cars.c b/src_rebuild/Game/C/cars.c index e1aebfc91..5e539056f 100644 --- a/src_rebuild/Game/C/cars.c +++ b/src_rebuild/Game/C/cars.c @@ -26,11 +26,7 @@ struct plotCarGlobals OTTYPE* ot; u_int intensity; u_short* pciv_clut; - u_int ShineyTPageASL16; - u_int ShineyClutASL16; u_char* damageLevel; - u_char* shineyTable; - int ghost; }; @@ -41,10 +37,24 @@ struct plotCarGlobals #endif MATRIX light_matrix = -{ { { 4096, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }, { 0, 0, 0 } }; +{ + { + { 4096, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } + }, + { 0, 0, 0 } +}; MATRIX colour_matrix = -{ { { 4032, 0, 0 }, { 3936, 0, 0 }, { 3520, 0, 0 } }, { 0, 0, 0 } }; +{ + { + { 4032, 0, 0 }, + { 3936, 0, 0 }, + { 3520, 0, 0 } + }, + { 0, 0, 0 } +}; // PHYSICS CAR_DATA car_data[MAX_CARS + 2]; // all cars + Tanner cbox + Camera cbox @@ -56,9 +66,9 @@ MODEL* gCleanWheelModelPtr; MODEL* gFastWheelModelPtr; MODEL* gDamWheelModelPtr; -// active carsg +// active cars CAR_DATA* active_car_list[MAX_CARS]; -BOUND_BOX bbox[MAX_CARS]; + u_char lightsOnDelay[MAX_CARS]; short FrontWheelRotation[MAX_CARS]; // offset 0x0 short BackWheelRotation[MAX_CARS]; // offset 0x30 @@ -250,7 +260,7 @@ void plotCarPolyGT3(int numTris, CAR_POLY *src, SVECTOR *vlist, SVECTOR *nlist, ofse = pg->damageLevel[src->originalindex]; - *(u_int*)&prim->u0 = (src->clut_uv0 & 0xffffU | pg->pciv_clut[palette + (src->clut_uv0 >> 0x10)] << 0x10) + ofse; + *(u_int*)&prim->u0 = pg->pciv_clut[(src->clut_uv0 >> 0x10) + palette] << 0x10 | (src->clut_uv0 & 0xffff) + ofse; *(u_int*)&prim->u1 = src->tpage_uv1 + ofse; *(u_int*)&prim->u2 = src->uv3_uv2 + ofse; @@ -269,6 +279,95 @@ void plotCarPolyGT3(int numTris, CAR_POLY *src, SVECTOR *vlist, SVECTOR *nlist, pg->primptr = (unsigned char*)prim; } + +#ifdef DYNAMIC_LIGHTING +void plotCarPolyGT3Lit(int numTris, CAR_POLY* src, SVECTOR* vlist, SVECTOR* nlist, plotCarGlobals* pg, int palette) +{ + int Z; + int otz; + SVECTOR* v2; + SVECTOR* v1; + SVECTOR* v0; + u_int indices; + POLY_GT3* prim; + u_int r0, r1, r2; + int ofse; + + prim = (POLY_GT3*)pg->primptr; + + int GT3rgb = pg->intensity | 0x34000000; + gte_ldrgb(>3rgb); + + while (numTris > 0) + { + indices = src->vindices; + + v0 = vlist + (indices & 0xff); + v1 = vlist + (indices >> 8 & 0xff); + v2 = vlist + (indices >> 16 & 0xff); + + gte_ldv3(v0, v1, v2); + + gte_rtpt(); + gte_nclip(); + + gte_stopz(&Z); + + gte_avsz3(); + + gte_stotz(&otz); + + if (Z > -1 && otz > 0) + { + indices = src->nindices; + + r0 = (u_int)(ushort)nlist[indices & 0xff].pad; + r1 = (u_int)(ushort)nlist[indices >> 8 & 0xff].pad; + r2 = (u_int)(ushort)nlist[indices >> 16 & 0xff].pad; + + *(u_int*)&prim->r0 = (r0 & 0xff) << 0x10 | r0; + *(u_int*)&prim->r1 = (r1 & 0xff) << 0x10 | r1; + *(u_int*)&prim->r2 = (r2 & 0xff) << 0x10 | r2; + + ofse = pg->damageLevel[src->originalindex]; + + *(u_int*)&prim->u0 = pg->pciv_clut[(src->clut_uv0 >> 0x10) + palette] << 0x10 | (src->clut_uv0 & 0xffff) + ofse; + *(u_int*)&prim->u1 = src->tpage_uv1 + ofse; + *(u_int*)&prim->u2 = src->uv3_uv2 + ofse; + + gte_stsxy3(&prim->x0, &prim->x1, &prim->x2); + + SVECTOR tmpPos; + gte_ldv0(v0); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prim->r0); + + gte_ldv0(v1); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prim->r1); + + gte_ldv0(v2); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prim->r2); + + setPolyGT3(prim); + addPrim(pg->ot + (otz >> 1), prim); + + prim++; + } + + src++; + numTris--; + } + + pg->primptr = (unsigned char*)prim; +} +#endif // DYNAMIC_LIGHTING + + // [D] [T] void plotCarPolyGT3nolight(int numTris, CAR_POLY *src, SVECTOR *vlist, plotCarGlobals *pg, int palette) { @@ -298,11 +397,9 @@ void plotCarPolyGT3nolight(int numTris, CAR_POLY *src, SVECTOR *vlist, plotCarGl gte_rtpt(); gte_nclip(); - gte_stopz(&Z); gte_avsz3(); - gte_stotz(&otz); if (Z > -1 && otz > 0) @@ -311,7 +408,7 @@ void plotCarPolyGT3nolight(int numTris, CAR_POLY *src, SVECTOR *vlist, plotCarGl ofse = pg->damageLevel[src->originalindex]; - *(u_int*)&prim->u0 = (src->clut_uv0 & 0xffffU | pg->pciv_clut[palette + (src->clut_uv0 >> 0x10)] << 0x10) + ofse; + *(u_int*)&prim->u0 = pg->pciv_clut[(src->clut_uv0 >> 0x10) + palette] << 0x10 | (src->clut_uv0 & 0xffff) + ofse; *(u_int*)&prim->u1 = src->tpage_uv1 + ofse; *(u_int*)&prim->u2 = src->uv3_uv2 + ofse; @@ -342,9 +439,9 @@ void setupLightingMatrices(void) gte_SetColorMatrix(&colour_matrix); gte_SetLightMatrix(&light_matrix); - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { - gte_SetBackColor(64, 64, 64); + gte_SetBackColor(48, 48, 48); } else { @@ -362,35 +459,31 @@ void restoreLightingMatrices(void) // [D] [T] void ComputeCarLightingLevels(CAR_DATA* cp, char detail) { - MATRIX& scratchPadMat = *(MATRIX*)((u_char*)getScratchAddr(0) + 0x344); +#ifdef PSX + MATRIX& scratchPadMat = *(MATRIX*)((u_char*)getScratchAddr(0) + 0x100); +#else + MATRIX scratchPadMat; +#endif int doLight; - int orW; - int orY; + int orW, orY; MODEL* model; - int num_norms; - int count; + int num_norms, count; SVECTOR* ppads; SVECTOR* norms; - SVECTOR lightsourcevector; - SVECTOR colour; - CVECTOR c0; - CVECTOR c1; - CVECTOR c2; + SVECTOR colour, lightsourcevector; + CVECTOR c0, c1, c2; u_int GT3rgb; - if (gTimeOfDay > -1) + if (gTimeOfDay == TIME_NIGHT) { - if (gTimeOfDay < 3) - { - lightsourcevector = day_vectors[GameLevel]; - colour = day_colours[GameLevel]; - } - else if (gTimeOfDay == 3) - { - lightsourcevector = night_vectors[GameLevel]; - colour = night_colours[GameLevel]; - } + lightsourcevector = night_vectors[GameLevel]; + colour = night_colours[GameLevel]; + } + else + { + lightsourcevector = day_vectors[GameLevel]; + colour = day_colours[GameLevel]; } InvertMatrix(&cp->hd.where, &scratchPadMat); @@ -398,71 +491,58 @@ void ComputeCarLightingLevels(CAR_DATA* cp, char detail) gte_ldv0(&lightsourcevector); gte_rtv0(); - gte_stsv(light_matrix.m[0]); - doLight = 0; - colour_matrix.m[0][0] = colour.vx; colour_matrix.m[1][0] = colour.vy; colour_matrix.m[2][0] = colour.vz; - if (gTimeOfDay != 3) - { - orY = cp->st.n.orientation[1] - cp->ap.qy; - - if (orY < 1) - orY = cp->ap.qy - cp->st.n.orientation[1]; - - orW = cp->st.n.orientation[3] - cp->ap.qw; + orY = ABS(cp->st.n.orientation[1] - cp->ap.qy); + orW = ABS(cp->st.n.orientation[3] - cp->ap.qw); - if (orW < 1) - orW = cp->ap.qw - cp->st.n.orientation[3]; + doLight = 0; - if ((orY + orW > 200) || (cp->lowDetail != (detail | lightning))) - doLight = 1; + if ((orY + orW > 200) || (cp->lowDetail != (detail | lightning))) + doLight = 1; - if ((gTimeOfDay == 0 || gTimeOfDay == 2) && (cp->id & 0xf) == (CameraCnt & 0xfU)) - doLight = 1; + if ((M_BIT(gTimeOfDay) & (M_BIT(TIME_DAWN) | M_BIT(TIME_DUSK))) && (cp->id & 15) == (CameraCnt & 15)) + doLight = 1; + if (doLight) + { setupLightingMatrices(); - if (doLight) - { - GT3rgb = combointensity & 0xffffffU | 0x34000000; - gte_ldrgb(>3rgb); - - cp->ap.qy = cp->st.n.orientation[1]; - cp->ap.qw = cp->st.n.orientation[3]; - cp->lowDetail = detail | lightning; - - if (detail == 0) - model = gCarLowModelPtr[cp->ap.model]; - else - model = gCarCleanModelPtr[cp->ap.model]; + GT3rgb = combointensity & 0xffffffU | 0x34000000; + gte_ldrgb(>3rgb); - num_norms = model->num_point_normals / 3; - norms = (SVECTOR*)model->point_normals; + cp->ap.qy = cp->st.n.orientation[1]; + cp->ap.qw = cp->st.n.orientation[3]; + cp->lowDetail = detail | lightning; - ppads = gTempCarVertDump[cp->id]; - count = num_norms;// +1; + if (detail == 0) + model = gCarLowModelPtr[cp->ap.model]; + else + model = gCarCleanModelPtr[cp->ap.model]; - while (count >= 0) - { - gte_ldv3(&norms[0], &norms[1], &norms[2]); + num_norms = model->num_point_normals / 3; + norms = (SVECTOR*)model->point_normals; - gte_ncct(); + ppads = gTempCarVertDump[cp->id]; + count = num_norms;// +1; - gte_strgb3(&c0, &c1, &c2); + while (count >= 0) + { + gte_ldv3(&norms[0], &norms[1], &norms[2]); + gte_ncct(); + gte_strgb3(&c0, &c1, &c2); - ppads[0].pad = *(short*)&c0; - ppads[1].pad = *(short*)&c1; - ppads[2].pad = *(short*)&c2; + ppads[0].pad = *(short*)&c0; + ppads[1].pad = *(short*)&c1; + ppads[2].pad = *(short*)&c2; - count--; - norms += 3; - ppads += 3; - } + count--; + norms += 3; + ppads += 3; } restoreLightingMatrices(); @@ -487,16 +567,16 @@ void DrawWheelObject(MODEL* model, SVECTOR* verts, int transparent, int wheelnum poly = (POLY_FT4*)current->primptr; clut = texture_cluts[src->texture_set][src->texture_id]; - tpage = texture_pages[src->texture_set]; + tpage = texture_pages[src->texture_set] | 0x20; if (gTimeOfDay > -1) { - if (gTimeOfDay < 3) + if (gTimeOfDay < TIME_NIGHT) { bright = combointensity & 0xffffffU | 0x2c000000; dim = (combointensity & 0xfcfcfcU) >> 2 | 0x2c000000; } - else if (gTimeOfDay == 3) + else if (gTimeOfDay == TIME_NIGHT) { combo = (combointensity & 0xffU) / 3; combo = combo << 0x10 | combo << 8 | combo; @@ -541,19 +621,12 @@ void DrawWheelObject(MODEL* model, SVECTOR* verts, int transparent, int wheelnum gte_stsxy3(&poly->x1, &poly->x3, &poly->x2); - poly->u0 = src->uv0.u; - poly->v0 = src->uv0.v; + *(u_short*)&poly->u0 = *(u_short*)&src->uv0; + *(u_short*)&poly->u1 = *(u_short*)&src->uv1; + *(u_short*)&poly->u2 = *(u_short*)&src->uv3; + *(u_short*)&poly->u3 = *(u_short*)&src->uv2; poly->clut = clut; - - poly->u1 = src->uv1.u; - poly->v1 = src->uv1.v; - poly->tpage = tpage | 0x20; - - poly->u2 = src->uv3.u; - poly->v2 = src->uv3.v; - - poly->u3 = src->uv2.u; - poly->v3 = src->uv2.v; + poly->tpage = tpage; poly++; } @@ -566,27 +639,25 @@ void DrawWheelObject(MODEL* model, SVECTOR* verts, int transparent, int wheelnum void DrawCarWheels(CAR_DATA *cp, MATRIX *RearMatrix, VECTOR *pos, int zclip) { short wheelSize; - int FW1z; - int FW2z; - int BW1z; - int BW2z; - int FrontWheelIncrement; - int BackWheelIncrement; + int FW1z, FW2z; + int BW1z, BW2z; + int FrontWheelIncrement, BackWheelIncrement; int sizeScale; int wheelnum; SVECTOR* VertPtr; - MODEL* model; SVECTOR* wheelDisp; WHEEL* wheel; int car_id; - MODEL *WheelModelBack; - MODEL *WheelModelFront; + MODEL* WheelModelBack; + MODEL* WheelModelFront; + MODEL* model; -#if 0 //def PSX +#ifdef PSX MATRIX& FrontMatrix = *(MATRIX*)(u_char*)getScratchAddr(0); MATRIX& SteerMatrix = *(MATRIX*)((u_char*)getScratchAddr(0) + sizeof(MATRIX)); VECTOR& WheelPos = *(VECTOR*)((u_char*)getScratchAddr(0) + sizeof(MATRIX) * 2); SVECTOR& sWheelPos = *(SVECTOR*)((u_char*)getScratchAddr(0) + sizeof(MATRIX) * 2 + sizeof(VECTOR)); + static_assert(sizeof(MATRIX) * 2 + sizeof(VECTOR) + sizeof(SVECTOR) * 25 < 1024 - sizeof(_pct), "Scratchpad overflow"); #else MATRIX FrontMatrix; MATRIX SteerMatrix; @@ -803,8 +874,8 @@ void PlayerCarFX(CAR_DATA *cp) // [D] [T] void plotNewCarModel(CAR_MODEL* car, int palette) { -#if 0 //def PSX - plotCarGlobals& _pg = *(plotCarGlobals*)(u_char*)getScratchAddr(0); +#ifdef PSX + plotCarGlobals& _pg = *(plotCarGlobals*)((u_char*)getScratchAddr(0) + 1024 - sizeof(plotCarGlobals) - sizeof(_pct)); #else plotCarGlobals _pg; #endif @@ -820,9 +891,9 @@ void plotNewCarModel(CAR_MODEL* car, int palette) if (gTimeOfDay > -1) { - if (gTimeOfDay < 3) + if (gTimeOfDay < TIME_NIGHT) lightlevel = combointensity | 0x30000000; - else if (gTimeOfDay == 3) + else if (gTimeOfDay == TIME_NIGHT) lightlevel = 0x302a2a2a; } @@ -852,15 +923,23 @@ void plotNewCarModel(CAR_MODEL* car, int palette) // draw car body _pg.ot = (OTTYPE*)(current->ot + 4); - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { _pg.intensity = (combointensity & 0xfcfcf0U) >> 2; +#ifdef DYNAMIC_LIGHTING + (gEnableDlights ? plotCarPolyGT3Lit : plotCarPolyGT3)(car->numGT3, car->pGT3, car->vlist, car->nlist, &_pg, palette); +#else plotCarPolyGT3nolight(car->numGT3, car->pGT3, car->vlist, &_pg, palette); +#endif // DYNAMIC_LIGHTING } else { _pg.intensity = combointensity & 0xffffff; +#ifdef DYNAMIC_LIGHTING + (gEnableDlights ? plotCarPolyGT3Lit : plotCarPolyGT3)(car->numGT3, car->pGT3, car->vlist, car->nlist, &_pg, palette); +#else plotCarPolyGT3(car->numGT3, car->pGT3, car->vlist, car->nlist, &_pg, palette); +#endif } current->primptr = (char*)_pg.primptr; @@ -892,7 +971,8 @@ void buildNewCars(void) // [D] [T] void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first) { - u_char ptype, clut; + ushort clut; + u_char ptype, carid; u_char *polyList; CAR_POLY *cp; @@ -1001,12 +1081,14 @@ void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first) { POLYGT3* pgt3 = (POLYGT3*)polyList; - clut = GetCarPalIndex(pgt3->texture_set); - civ_clut[clut][pgt3->texture_id][0] = texture_cluts[pgt3->texture_set][pgt3->texture_id]; + carid = GetCarPalIndex(pgt3->texture_set); + clut = (carid - 1) * 6 * 32 + pgt3->texture_id * 6; + + civ_clut[carid][pgt3->texture_id][0] = texture_cluts[pgt3->texture_set][pgt3->texture_id]; cp->vindices = M_INT_4R(pgt3->v0, pgt3->v1, pgt3->v2, 0); cp->nindices = M_INT_4R(pgt3->n0, pgt3->n1, pgt3->n2, 0); - cp->clut_uv0 = M_INT_2((clut * 384 + pgt3->texture_id * 12 - 384) >> 1, * (ushort*)&pgt3->uv0); + cp->clut_uv0 = M_INT_2(clut, *(ushort*)&pgt3->uv0); cp->tpage_uv1 = M_INT_2(texture_pages[pgt3->texture_set], *(ushort *)&pgt3->uv1); cp->uv3_uv2 = *(ushort *)&pgt3->uv2; cp->originalindex = i; @@ -1019,12 +1101,14 @@ void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first) { POLYGT4* pgt4 = (POLYGT4*)polyList; - clut = GetCarPalIndex(pgt4->texture_set); - civ_clut[clut][pgt4->texture_id][0] = texture_cluts[pgt4->texture_set][pgt4->texture_id]; + carid = GetCarPalIndex(pgt4->texture_set); + clut = (carid - 1) * 6 * 32 + pgt4->texture_id * 6; + + civ_clut[carid][pgt4->texture_id][0] = texture_cluts[pgt4->texture_set][pgt4->texture_id]; cp->vindices = M_INT_4R(pgt4->v0, pgt4->v1, pgt4->v2, 0); cp->nindices = M_INT_4R(pgt4->n0, pgt4->n1, pgt4->n2, 0); - cp->clut_uv0 = M_INT_2((clut * 384 + pgt4->texture_id * 12 - 384) >> 1, *(ushort*)&pgt4->uv0); + cp->clut_uv0 = M_INT_2(clut, *(ushort*)&pgt4->uv0); cp->tpage_uv1 = M_INT_2(texture_pages[pgt4->texture_set], *(ushort*)&pgt4->uv1); cp->uv3_uv2 = *(ushort*)&pgt4->uv2; cp->originalindex = i; @@ -1033,7 +1117,7 @@ void buildNewCarFromModel(CAR_MODEL *car, MODEL *model, int first) cp->vindices = M_INT_4R(pgt4->v0, pgt4->v2, pgt4->v3, 0); cp->nindices = M_INT_4R(pgt4->n0, pgt4->n2, pgt4->n3, 0); - cp->clut_uv0 = M_INT_2((clut * 384 + pgt4->texture_id * 12 - 384) >> 1, *(ushort*)&pgt4->uv0); + cp->clut_uv0 = M_INT_2(clut, *(ushort*)&pgt4->uv0); cp->tpage_uv1 = M_INT_2(texture_pages[pgt4->texture_set], *(ushort *)&pgt4->uv2); cp->uv3_uv2 = *(ushort *)&pgt4->uv3; cp->originalindex = i; @@ -1158,7 +1242,7 @@ void MangleWheelModels(void) src++; } - } while (++i < 3); + } // HACK: Show clean model only in Rio. //if (GameLevel == 3) @@ -1192,24 +1276,23 @@ void ProcessPalletLump(char *lump_ptr, int lump_size) texnum = buffPtr[1]; tpageindex = buffPtr[2]; clut_number = buffPtr[3]; + buffPtr += 4; if (clut_number == -1) { // store clut - LoadImage(&clutpos, (u_long*)(buffPtr + 4)); + LoadImage(&clutpos, (u_long*)buffPtr); + buffPtr += 8; clutValue = GetClut(clutpos.x, clutpos.y); - *clutTablePtr++ = clutValue; - IncrementClutNum(&clutpos); - buffPtr += 12; + *clutTablePtr++ = clutValue; } else { // use stored clut clutValue = clutTable[clut_number]; - buffPtr += 4; } civ_clut[GetCarPalIndex(tpageindex)][texnum][palette + 1] = clutValue; @@ -1219,8 +1302,6 @@ void ProcessPalletLump(char *lump_ptr, int lump_size) // [D] [T] void DrawCarObject(CAR_MODEL* car, MATRIX* matrix, VECTOR* pos, int palette, CAR_DATA* cp, int detail) { - static u_long savedSP; - VECTOR modelLocation; SVECTOR cog; @@ -1245,11 +1326,7 @@ void DrawCarObject(CAR_MODEL* car, MATRIX* matrix, VECTOR* pos, int palette, CAR gte_SetTransVector(&modelLocation); - savedSP = SetSp((u_long)((u_char*)getScratchAddr(0) + 0x308)); - plotNewCarModel(car, palette); - - SetSp(savedSP); } // [D] [T] [A] @@ -1262,10 +1339,9 @@ void DrawCar(CAR_DATA* cp, int view) CAR_MODEL* CarModelPtr; int model; CVECTOR col; - VECTOR pos; + SVECTOR d; + VECTOR pos, dist; VECTOR corners[4]; - VECTOR d; - VECTOR dist; MATRIX workmatrix; D_CHECK_ERROR(cp < car_data, "Invalid car"); @@ -1435,7 +1511,9 @@ void DrawCar(CAR_DATA* cp, int view) if (doSmoke && WheelSpeed + 399999U < 1199999) AddSmokingEngine(cp, doSmoke - 1, WheelSpeed); +#if ENABLE_GAME_ENCHANCEMENTS AddExhaustSmoke(cp, doSmoke > 1, WheelSpeed); +#endif SetShadowPoints(cp, corners); PlaceShadowForCar(corners, 4, 10, yVal < 0 ? 0 : 2); diff --git a/src_rebuild/Game/C/cars.h b/src_rebuild/Game/C/cars.h index 072790a04..7ebec0e53 100644 --- a/src_rebuild/Game/C/cars.h +++ b/src_rebuild/Game/C/cars.h @@ -11,7 +11,6 @@ extern CAR_DATA car_data[MAX_CARS + 2]; // all cars + Tanner cbox + Camera cbox // active cars extern CAR_DATA* active_car_list[MAX_CARS]; -extern BOUND_BOX bbox[MAX_CARS]; extern unsigned char lightsOnDelay[MAX_CARS]; extern CAR_MODEL NewCarModel[MAX_CAR_MODELS]; diff --git a/src_rebuild/Game/C/cell.c b/src_rebuild/Game/C/cell.c index 15b147279..3a7aff13c 100644 --- a/src_rebuild/Game/C/cell.c +++ b/src_rebuild/Game/C/cell.c @@ -7,7 +7,7 @@ int cell_object_index = 0; CELL_OBJECT cell_object_buffer[1024]; -unsigned char cell_object_computed_values[2048]; +u_char cell_object_computed_values[2048]; extern u_char NumPlayers; @@ -69,11 +69,11 @@ PACKED_CELL_OBJECT * GetFirstPackedCop(int cellx, int cellz, CELL_ITERATOR *pci, 8767,555,445,223 - objects of list 2 0x8000 - end of cell objects */ - - while (cell->num != (level | 0x4000)) // skip until we reach the needed list header + + level |= 0x4000; + while (cell->num != level) // skip until we reach the needed list header { cell++; - if (cell->num & 0x8000) // end of cell objects? return NULL; } @@ -86,8 +86,8 @@ PACKED_CELL_OBJECT * GetFirstPackedCop(int cellx, int cellz, CELL_ITERATOR *pci, pci->pcd = cell; - num = cell->num; - ppco = &cell_objects[num & 0x3fff]; + num = cell->num & 16383; + ppco = &cell_objects[num]; if (ppco->value == 0xffff && (ppco->pos.vy & 1)) { @@ -95,9 +95,9 @@ PACKED_CELL_OBJECT * GetFirstPackedCop(int cellx, int cellz, CELL_ITERATOR *pci, } else if (use_computed) { - value = 1 << (num & 7) & 0xffff; + value = 1 << (num & 7); - if (cell_object_computed_values[(num & 0x3fff) >> 3] & value) // get cached value + if (cell_object_computed_values[num / 8] & value) // get cached value { ppco = GetNextPackedCop(pci); pci->ppco = ppco; @@ -105,7 +105,7 @@ PACKED_CELL_OBJECT * GetFirstPackedCop(int cellx, int cellz, CELL_ITERATOR *pci, return ppco; } - cell_object_computed_values[(num & 0x3fff) >> 3] |= value; + cell_object_computed_values[num / 8] |= value; } pci->ppco = ppco; @@ -135,20 +135,19 @@ PACKED_CELL_OBJECT* GetNextPackedCop(CELL_ITERATOR* pci) if (num & 0x4000) // end of list? return NULL; - ppco = &cell_objects[num & 0x3fff]; + num &= 16383; + ppco = &cell_objects[num]; } while (ppco->value == 0xffff && (ppco->pos.vy & 1)); if (!pci->use_computed) break; - value = 1 << (num & 7) & 0xffff; - - if ((cell_object_computed_values[(num & 0x3fff) >> 3] & value) == 0) + value = 1 << (num & 7); + if ((cell_object_computed_values[num / 8] & value) == 0) { - cell_object_computed_values[(num & 0x3fff) >> 3] |= value; + cell_object_computed_values[num / 8] |= value; break; } - } while (true); pci->pcd = celld; @@ -157,34 +156,20 @@ PACKED_CELL_OBJECT* GetNextPackedCop(CELL_ITERATOR* pci) return ppco; } + // [D] [T] CELL_OBJECT* UnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near) { + int newIndex; CELL_OBJECT* pco; if (ppco == NULL) return NULL; - pco = &cell_object_buffer[cell_object_index]; - cell_object_index = cell_object_index + 1 & 0x3ff; - - pco->pos.vx = near->x + (((ppco->pos.vx - near->x) << 0x10) >> 0x10); - pco->pos.vz = near->z + (((ppco->pos.vz - near->z) << 0x10) >> 0x10); + pco = &cell_object_buffer[newIndex = cell_object_index]; + cell_object_index = newIndex + 1 & 1023; - pco->pos.vy = (ppco->pos.vy << 0x10) >> 0x11; - pco->yang = ppco->value & 0x3f; - pco->type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10); + QuickUnpackCellObject(ppco, near, pco); return pco; -} - -// [D] [T] -void QuickUnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near, CELL_OBJECT* pco) -{ - pco->pos.vx = near->x + (((ppco->pos.vx - near->x) << 0x10) >> 0x10); - pco->pos.vz = near->z + (((ppco->pos.vz - near->z) << 0x10) >> 0x10); - - pco->pos.vy = (ppco->pos.vy << 0x10) >> 0x11; - pco->yang = ppco->value & 0x3f; - pco->type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10); } \ No newline at end of file diff --git a/src_rebuild/Game/C/cell.h b/src_rebuild/Game/C/cell.h index e8474ebfd..15767f6a2 100644 --- a/src_rebuild/Game/C/cell.h +++ b/src_rebuild/Game/C/cell.h @@ -9,6 +9,15 @@ extern PACKED_CELL_OBJECT * GetFirstPackedCop(int cellx, int cellz, CELL_ITERATO extern PACKED_CELL_OBJECT* GetNextPackedCop(CELL_ITERATOR* pci); // 0x0003F5F0 extern CELL_OBJECT* UnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near); // 0x000418E8 -extern void QuickUnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near, CELL_OBJECT* pco); +inline void QuickUnpackCellObject(PACKED_CELL_OBJECT* ppco, XZPAIR* near, CELL_OBJECT* pco) +{ + pco->pos.vx = near->x + (short)(ppco->pos.vx - near->x); + pco->pos.vz = near->z + (short)(ppco->pos.vz - near->z); + + pco->pos.vy = (short)ppco->pos.vy >> 1; + + pco->yang = ppco->value & 63; + pco->type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10); +} #endif diff --git a/src_rebuild/Game/C/civ_ai.c b/src_rebuild/Game/C/civ_ai.c index b5a037f96..fd6822f2e 100644 --- a/src_rebuild/Game/C/civ_ai.c +++ b/src_rebuild/Game/C/civ_ai.c @@ -24,9 +24,11 @@ #include "objcoll.h" #include "overlay.h" #include "cutrecorder.h" +#include "draw.h" const u_char speedLimits[3] = { 56, 97, 138 }; +#ifdef DEBUG struct { int NumPingedIn; @@ -40,6 +42,7 @@ struct int TooClosePlayer; int InvalidRegion; } civPingTest; +#endif // DEBUG char modelRandomList[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 1, 0, 4 }; u_char reservedSlots[MAX_CARS] = { 0 }; @@ -75,13 +78,15 @@ int test555 = 0; #ifdef _DEBUG #define CIV_STATE_SET_CONFUSED(cp) \ - printInfo("CIV confused: at %s, %d\n", __FUNCTION__, __LINE__);\ + printInfo("CIV confused: at %s, %d\n", FUNCNAME, __LINE__);\ cp->ai.c.thrustState = 3; cp->ai.c.ctrlState = 7; #else #define CIV_STATE_SET_CONFUSED(cp) \ cp->ai.c.thrustState = 3; cp->ai.c.ctrlState = 7; #endif +int GetNodePos(DRIVER2_STRAIGHT* straight, DRIVER2_JUNCTION* junction, DRIVER2_CURVE* curve, int distAlongPath, CAR_DATA* cp, int* x, int* z, int laneNo); + // [D] [T] int InitCar(CAR_DATA* cp, int direction, LONGVECTOR4* startPos, unsigned char control, int model, int palette, char* extraData) { @@ -234,6 +239,66 @@ void CivCarFX(CAR_DATA* cp) AddBrakeLight(cp); } +int GetLeftBoundLane(DRIVER2_ROAD_INFO& roadInfo, int oppDir) +{ + int i, laneCount, laneNo; + + laneCount = ROAD_WIDTH_IN_LANES(&roadInfo); + laneNo = laneCount; + + for (i = laneNo - 1; i >= 0; i--) + { + if (ROAD_IS_AI_LANE(&roadInfo, i) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, i)) + { + test42 = ROAD_LANE_DIR(&roadInfo, i) ^ 1; + laneNo = i; + + if (test42 == 0) + { + if (oppDir != 0) + break; + } + else + { + if (oppDir == 0) + break; + } + } + } + + return laneNo; +}; + +int GetRightBoundLane(DRIVER2_ROAD_INFO& roadInfo, int oppDir) +{ + int i, laneCount, laneNo; + + laneCount = ROAD_WIDTH_IN_LANES(&roadInfo); + laneNo = ROAD_IS_LEFTMOST_LANE_PARKING(&roadInfo); + + for (i = laneNo; i < laneCount; i++) + { + if (ROAD_IS_AI_LANE(&roadInfo, i) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, i)) + { + test555 = ROAD_LANE_DIR(&roadInfo, i) ^ 1; + laneNo = i; + + if (test555 == 0) + { + if (oppDir != 0) + break; + } + else + { + if (oppDir == 0) + break; + } + } + } + + return laneNo; +} + // [D] [T] int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist, CIV_ROUTE_ENTRY* oldNode) { @@ -243,34 +308,22 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist DRIVER2_ROAD_INFO currentRoadInfo; DRIVER2_ROAD_INFO roadInfo; - int currentRoadId = 0; int tmpNewRoad[2]; - int newExit = 0; int tmpNewLane[2]; int laneFit[2]; short validExitIdx[4]; - int newLane; - int newRoad; - - int numExits; - int leftLane; - int rightLane; + int newRoad, newLane, newExit, numExits; + int currentRoadId, leftLane, rightLane; - int oldOppDir; - int oppDir; - int turnDir; - int currentLaneDir; + int oppDir, oldOppDir; + int turnDir, currentLaneDir; currentRoadId = cp->ai.c.currentRoad; if (GetSurfaceRoadInfo(¤tRoadInfo, currentRoadId)) { - int widthInLanes; int laneNo; - int count; - - widthInLanes = ROAD_WIDTH_IN_LANES(¤tRoadInfo); currentLaneDir = ROAD_LANE_DIR(¤tRoadInfo, cp->ai.c.currentLane); @@ -284,76 +337,36 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist dx = oldNode->x - currentRoadInfo.curve->Midx; dz = oldNode->z - currentRoadInfo.curve->Midz; - oldOppDir = DIFF_ANGLES(ratan2(dx, dz), oldNode->dir); // (((oldNode->dir - ratan2(dx, dz)) + 2048U & 0xfff) - 2048); + oldOppDir = DIFF_ANGLES(ratan2(dx, dz), oldNode->dir); oldOppDir = (oldOppDir < 1) * 2048; } // first road is picked from road direction - tmpNewRoad[0] = ((short*)currentRoadInfo.ConnectIdx)[(oldOppDir > 0) * 2]; + tmpNewRoad[0] = currentRoadInfo.ConnectIdx[(oldOppDir > 0) * 2]; // and second picked from lane direction - tmpNewRoad[1] = ((short*)currentRoadInfo.ConnectIdx)[(currentLaneDir > 0) ? 3 : 1]; - - count = widthInLanes; // counter - laneNo = widthInLanes; // bestLane - - do - { - count--; - if (ROAD_IS_AI_LANE(¤tRoadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(¤tRoadInfo, count)) - { - test42 = ROAD_LANE_DIR(¤tRoadInfo, count); - laneNo = count; - } - } while (count >= 0); + tmpNewRoad[1] = currentRoadInfo.ConnectIdx[(currentLaneDir > 0) ? 3 : 1]; + laneNo = GetLeftBoundLane(currentRoadInfo, currentLaneDir); - if (currentLaneDir == 0) - leftLane = laneNo & 0xff; + if (oldOppDir == 0) + leftLane = laneNo; else - rightLane = laneNo & 0xff; + rightLane = laneNo; - // ifhas fast lane, use second lane - count = ROAD_HAS_FAST_LANES(¤tRoadInfo); - laneNo = widthInLanes; - - while (count < widthInLanes) - { - if (ROAD_IS_AI_LANE(¤tRoadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(¤tRoadInfo, count)) - { - test555 = ROAD_LANE_DIR(¤tRoadInfo, count) ^ 1; - laneNo = count; - - if (test555 == 0) - { - if (currentLaneDir != 0) - break; - } - else - { - if (currentLaneDir == 0) - break; - } - } - laneNo = widthInLanes; - count++; - } + laneNo = GetRightBoundLane(currentRoadInfo, currentLaneDir); - if (currentLaneDir != 0) - leftLane = laneNo & 0xff; + if (oldOppDir != 0) + leftLane = laneNo; else - rightLane = laneNo & 0xff; + rightLane = laneNo; } newLane = -1; if (IS_JUNCTION_SURFACE(tmpNewRoad[0])) { - int bestExit; - - int exitFrom; - int exitCnt; + int exitFrom, exitCnt, bestExit; int rnd; - numExits = 0; cp->ai.c.changeLaneCount = 0; jn = GET_JUNCTION(tmpNewRoad[0]); @@ -362,15 +375,13 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist // check if road is valid for this junction // by determining connection with junction - exitCnt = 0; - while(exitCnt < 4) + for(exitCnt = 0; exitCnt < 4; exitCnt++) { if(jn->ExitIdx[exitCnt] == currentRoadId) { exitFrom = exitCnt; break; } - exitCnt++; } if (exitFrom == -1) @@ -380,45 +391,46 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist } // check directions of exits - //printWarning("Checking directions, exitFrom: %d, \n", exitFrom); - exitCnt = 0; - do { - int exitSurfId; - int exitIdx = (exitFrom + exitCnt + 1) % 4; - int valid; + numExits = 0; + + // only need 3 cycles because we don't want make U-turns + for (exitCnt = 0; exitCnt < 3; exitCnt++) + { + int exitSurfId, exitIdx, valid; + + exitIdx = (exitFrom + exitCnt + 1) % 4; valid = 0; exitSurfId = jn->ExitIdx[exitIdx]; if (exitSurfId != -1) { + int turnAng; int exitDir; exitDir = ((exitIdx + 4) - exitFrom) % 4; - //exitDir = exitDir - (exitDir / 4) * 4; if (exitDir == 1) - *turnAngle = -1024; // left + turnAng = -1024; // left else if (exitDir == 2) - *turnAngle = 0; // forward + turnAng = 0; // forward else if (exitDir == 3) - *turnAngle = 1024; // right + turnAng = 1024; // right else - *turnAngle = 0; // forward again? + turnAng = 0; // forward again? test123 = 666; test555 = 666; test42 = 666; // current node direction and new direction - turnDir = oldNode->dir + *turnAngle; + turnDir = oldNode->dir + turnAng; if (GetSurfaceRoadInfo(&roadInfo, exitSurfId)) { - int turnAng; int dx, dz; - int laneCount; + int numLanes; - laneCount = ROAD_WIDTH_IN_LANES(&roadInfo); + numLanes = ROAD_WIDTH_IN_LANES(&roadInfo); if(roadInfo.straight) { @@ -429,94 +441,42 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist dx = oldNode->x - roadInfo.curve->Midx; dz = oldNode->z - roadInfo.curve->Midz; - oppDir = DIFF_ANGLES(ratan2(dx, dz), turnDir);// ((turnDir - ratan2(dx, dz)) + 2048U & 0xfff) - 2048; // [A] + oppDir = DIFF_ANGLES(ratan2(dx, dz), turnDir); oppDir = (oppDir < 1) * 2048; } - - turnAng = *turnAngle; - - if (oppDir == 0) - turnAng = -turnAng; - + if (turnAng == 0) // going forward { if (oppDir != oldOppDir) // next road is flipped - newLane = laneCount - (cp->ai.c.currentLane + 1); + newLane = numLanes - (cp->ai.c.currentLane + 1); else newLane = cp->ai.c.currentLane; - - // goes on invalid lane? - // [A] bug fix with exitDir == 0 - if (oppDir == 0 && exitDir == 0 || !ROAD_IS_AI_LANE(&roadInfo, newLane)) - newLane = -1; } else if (turnAng == -1024) // going left { - int count; - - //printInfo("check left\n"); - - count = ROAD_HAS_FAST_LANES(&roadInfo); // lane counter - newLane = laneCount; - - // check if allowed to go on any of lanes - while (count < laneCount) - { - if (ROAD_IS_AI_LANE(&roadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, count)) - { - test555 = (ROAD_LANE_DIR(&roadInfo, count) ^ 1) & 1; - newLane = count; - - if (test555 == 0) - { - if (oppDir != 0) - break; - } - else - { - if (oppDir == 0) - break; - } - } - - count++; - newLane = laneCount; - } + newLane = GetRightBoundLane(roadInfo, oppDir); } else if (turnAng == 1024) { - int count; - - count = laneCount; // lane counter - newLane = laneCount; - - do - { - if (ROAD_IS_AI_LANE(&roadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, count)) - { - test42 = (ROAD_LANE_DIR(&roadInfo, count) ^ 1) & 1; - - if (test42 == 0) - { - if (oppDir != 0) - newLane = count; - } - else - { - if (oppDir == 0) - newLane = count; - } - - } - count--; - } while (count >= 0); + newLane = GetLeftBoundLane(roadInfo, oppDir); } // validate lane - if (turnAng == 0 || newLane >= 0 && newLane < laneCount) + if (newLane >= 0 && newLane < numLanes) { valid = ROAD_IS_AI_LANE(&roadInfo, newLane) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, newLane); } + + if (oppDir != oldOppDir) + { + if (currentLaneDir == ROAD_LANE_DIR(&roadInfo, newLane)) + valid = 0; + } + else + { + if (currentLaneDir != ROAD_LANE_DIR(&roadInfo, newLane)) + valid = 0; + } } } @@ -529,10 +489,7 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist { validExitIdx[exitCnt] = 42; } - - // only need 3 cycles because we don't want make U-turns - exitCnt++; - } while (exitCnt < 3); + } if (leftLane != rightLane && numExits != 1 && ROAD_LANES_COUNT(¤tRoadInfo) > 1) { @@ -580,11 +537,9 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist newRoad = jn->ExitIdx[bestExit]; - if (turnAngle != NULL) { int invExit; invExit = (bestExit + 4 - exitFrom) % 4; - //invExit = invExit - (invExit / 4) * 4; if (invExit == 1) *turnAngle = -1024; @@ -660,9 +615,9 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist turnDir = oldNode->dir + *turnAngle; + // determine the new lane on the new road { - int numLanes; - int turnAng; + int numLanes, turnAng; numLanes = ROAD_WIDTH_IN_LANES(&roadInfo); turnAng = *turnAngle; @@ -677,7 +632,7 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist dx = oldNode->x - roadInfo.curve->Midx; dz = oldNode->z - roadInfo.curve->Midz; - oppDir = DIFF_ANGLES(ratan2(dx, dz), turnDir); // (((turnDir - ratan2(dx, dz)) + 2048U & 0xfff) - 2048); + oppDir = DIFF_ANGLES(ratan2(dx, dz), turnDir); oppDir = (oppDir < 1) * 2048; } @@ -706,68 +661,14 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist } else if (turnAng == -1024) { - int count; - - count = ROAD_HAS_FAST_LANES(&roadInfo); - newLane = numLanes; - - // check if allowed to go on any of lanes - while (count < numLanes) - { - if (ROAD_IS_AI_LANE(&roadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, count)) - { - test555 = (ROAD_LANE_DIR(&roadInfo, count) ^ 1) & 1; - newLane = count; - - if (test555 == 0) - { - if (oppDir != 0) - break; - } - else - { - if (oppDir == 0) - break; - } - } - - count++; - newLane = numLanes; - } - - //printWarning("car %d check left lane, chosen %d\n", cp->id, newLane); + newLane = GetRightBoundLane(roadInfo, oppDir); } else if (turnAng == 1024) { - int count; - - count = numLanes; - newLane = numLanes; - - do - { - if (ROAD_IS_AI_LANE(&roadInfo, count) && !ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, count)) - { - test42 = (ROAD_LANE_DIR(&roadInfo, count) ^ 1) & 1; - - if (test42 == 0) - { - if (oppDir != 0) - newLane = count; - } - else - { - if (oppDir == 0) - newLane = count; - } - - } - count--; - } while (count >= 0); - - //printWarning("car %d check right lane, chosen %d\n", cp->id, newLane); + newLane = GetLeftBoundLane(roadInfo, oppDir); } + if (*turnAngle != 0) { if (numLanes - 1 == newLane) @@ -812,11 +713,23 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist { if (tmpNewRoad[roadCnt] != -1) { + int px, pz; int dx, dz; int numLanes; numLanes = 0; + // [A] fix lane changingg issues + if(cp->ai.c.changeLaneCount > 0) + { + GetNodePos(currentRoadInfo.straight, NULL, currentRoadInfo.curve, oldNode->distAlongSegment, NULL, &px, &pz, cp->ai.c.currentLane); + } + else + { + px = oldNode->x; + pz = oldNode->z; + } + if (GetSurfaceRoadInfo(&roadInfo, tmpNewRoad[roadCnt])) { numLanes = ROAD_WIDTH_IN_LANES(&roadInfo); @@ -824,8 +737,8 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist // determine new lane by old node position if(roadInfo.straight) { - dx = (oldNode->x - roadInfo.straight->Midx); - dz = (oldNode->z - roadInfo.straight->Midz); + dx = (px - roadInfo.straight->Midx); + dz = (pz - roadInfo.straight->Midz); tmpNewLane[roadCnt] = ROAD_LANES_COUNT(&roadInfo) - (FIXEDH(dx * RCOS(roadInfo.straight->angle) - dz * RSIN(roadInfo.straight->angle)) + 512 >> 9); @@ -833,8 +746,8 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist } else { - dx = oldNode->x - roadInfo.curve->Midx; - dz = oldNode->z - roadInfo.curve->Midz; + dx = px - roadInfo.curve->Midx; + dz = pz - roadInfo.curve->Midz; tmpNewLane[roadCnt] = (SquareRoot0(dx * dx + dz * dz) >> 9) - roadInfo.curve->inside * 2; } @@ -851,7 +764,6 @@ int GetNextRoadInfo(CAR_DATA* cp, int randomExit, int* turnAngle, int* startDist } } - // fit new lane newLane = tmpNewLane[roadCnt]; @@ -1024,11 +936,44 @@ void InitNodeList(CAR_DATA* cp, EXTRA_CIV_DATA* extraData) cr->distAlongSegment = extraData->distAlongSegment; } +// [A] bug fixes the incorrect lane changes +void RemapLaneChange(CAR_DATA* cp) +{ + CIV_ROUTE_ENTRY* currentNode; + DRIVER2_ROAD_INFO roadInfo; + int numLanes, dx, dz; + int newLane; + + if (!GetSurfaceRoadInfo(&roadInfo, cp->ai.c.currentRoad)) + return; + + currentNode = &cp->ai.c.targetRoute[cp->ai.c.currentNode]; + numLanes = ROAD_WIDTH_IN_LANES(&roadInfo); + + // determine lane on new road by old node position + if (roadInfo.straight) + { + dx = (currentNode->x - roadInfo.straight->Midx); + dz = (currentNode->z - roadInfo.straight->Midz); + + newLane = ROAD_LANES_COUNT(&roadInfo) + - (FIXEDH(dx * RCOS(roadInfo.straight->angle) - dz * RSIN(roadInfo.straight->angle)) + 512 >> 9); + } + else + { + dx = currentNode->x - roadInfo.curve->Midx; + dz = currentNode->z - roadInfo.curve->Midz; + + newLane = (SquareRoot0(dx * dx + dz * dz) >> 9) - roadInfo.curve->inside * 2; + } + + cp->ai.c.currentLane = newLane; +} + // [D] [T] int GetNodePos(DRIVER2_STRAIGHT* straight, DRIVER2_JUNCTION* junction, DRIVER2_CURVE* curve, int distAlongPath, CAR_DATA* cp, int* x, int* z, int laneNo) { - unsigned char oldLane; - unsigned char changeLaneCount; + u_char oldLane, changeLaneCount; int angle; int distFromCentre; int sideShift; @@ -1104,13 +1049,10 @@ int GetNodePos(DRIVER2_STRAIGHT* straight, DRIVER2_JUNCTION* junction, DRIVER2_C // [D] [T] int CheckChangeLanes(DRIVER2_STRAIGHT* straight, DRIVER2_CURVE* curve, int distAlongSegment, CAR_DATA* cp, int tryToPark) { - int oldLane; - int currentLane; - int newLane; + int oldLane, newLane, currentLane; int trials; CAR_COSMETICS* car_cos; - int dx; - int dz; + int dx, dz; u_int theta; int length; CAR_DATA* lcp; @@ -1718,7 +1660,7 @@ int TrafficLightCycle(int exit) { int timeCnt; - timeCnt = CameraCnt - frameStart & 0x1ff; + timeCnt = CameraCnt - frameStart & 511; if (exit == 0 || exit == 2) { @@ -1732,7 +1674,7 @@ int TrafficLightCycle(int exit) if (timeCnt < 150) return 3; - else if (timeCnt > 199) + else if (timeCnt >= 200) return 1; return 2; @@ -1762,7 +1704,7 @@ void InitCivCars(void) closeEncounter = 3; } -const int EVENT_CAR_SPEED = 71; +const int EVENT_CAR_SPEED = 60; const int DistanceTriggerCarMoves = 5000; // [D] [T] [A] @@ -1839,7 +1781,7 @@ int CreateCivCarWotDrivesABitThenStops(int direction, LONGVECTOR4* startPos, LON } // [D] [T] -int CreateStationaryCivCar(int direction, long orientX, long orientZ, LONGVECTOR4* startPos, int externalModel, int palette, int controlFlags) +int CreateStationaryCivCar(int direction, int orientX, int orientZ, LONGVECTOR4* startPos, int externalModel, int palette, int controlFlags) { unsigned char* slot; CAR_DATA* newCar; @@ -1933,32 +1875,28 @@ int CreateStationaryCivCar(int direction, long orientX, long orientZ, LONGVECTOR return -1; } - -VECTOR baseLoc; -VECTOR randomLoc; -int dx = 0; // offset 0xAAB40 -int dy = 0; // offset 0xAAB44 -int dz = 0; // offset 0xAAB48 - #define PINGIN_DIST_WANTED_MULT (10) #define PINGIN_DIST_MULT (8) // [D] [T] [A] - some register is not properly decompiled int PingInCivCar(int minPingInDist) { - int model; - CAR_DATA* carCnt; - CAR_DATA* newCar; - - //DRIVER2_CURVE* curve; - //DRIVER2_STRAIGHT* straight; - +#ifdef PSX + DRIVER2_ROAD_INFO& roadInfo = *(DRIVER2_ROAD_INFO*)(u_char*)getScratchAddr(0); + EXTRA_CIV_DATA& civDat = *(EXTRA_CIV_DATA*)((u_char*)getScratchAddr(0) + sizeof(DRIVER2_ROAD_INFO)); + u_char* possibleLanes = ((u_char*)getScratchAddr(0) + sizeof(DRIVER2_ROAD_INFO) + sizeof(EXTRA_CIV_DATA)); + static_assert(sizeof(CELL_ITERATOR) + sizeof(char) + 12 < 1024 - sizeof(_pct), "scratchpad overflow"); +#else DRIVER2_ROAD_INFO roadInfo; - EXTRA_CIV_DATA civDat; u_char possibleLanes[12]; - // carDistLanes removed as it's unused +#endif LONGVECTOR4 pos; + VECTOR baseLoc, randomLoc; + int dx, dy, dz; + CAR_DATA* carCnt; + CAR_DATA* newCar; + int model; int distSq; int dir; int curveLength; @@ -1971,9 +1909,6 @@ int PingInCivCar(int minPingInDist) u_int retDistSq; unsigned char* slot; - //straight = NULL; - //curve = NULL; - civDat.distAlongSegment = -5; lane = -1; dir = 0xffffff; @@ -2020,8 +1955,6 @@ int PingInCivCar(int minPingInDist) newCar = NULL; - ClearMem((char*)&civDat, sizeof(civDat)); - baseLoc.vx = player[playerNum].spoolXZ->vx; baseLoc.vz = player[playerNum].spoolXZ->vz; @@ -2145,7 +2078,10 @@ int PingInCivCar(int minPingInDist) // wtf there were before? car wasn't set to 'confused' state if (!GetSurfaceRoadInfo(&roadInfo, roadSeg)) { +#ifdef DEBUG civPingTest.OffRoad++; +#endif // DEBUG + //CIV_STATE_SET_CONFUSED(newCar); return 0; } @@ -2181,7 +2117,7 @@ int PingInCivCar(int minPingInDist) // this is closest to OG decompiled. Works different! //if (( // ((tryPingInParkedCars && allowedToPark))) || - // ((ROAD_IS_AI_LANE(straight, i) && (((i != 0 || ((straight->NumLanes & 0x40U) == 0)) && (((straight->NumLanes & 0xffffff0f) * 2 - 1 != i || ((straight->NumLanes & 0x80U) == 0)))))))) + // ((ROAD_IS_AI_LANE(&roadInfo, i) && (((i != 0 || ((roadInfo.NumLanes & 0x40U) == 0)) && (((roadInfo.NumLanes & 0xffffff0f) * 2 - 1 != i || ((roadInfo.NumLanes & 0x80U) == 0)))))))) // pick only non-parkable driveable lanes if parked cars not requested if (tryPingInParkedCars && allowedToPark || ROAD_IS_AI_LANE(&roadInfo, i) && !allowedToPark) @@ -2194,6 +2130,8 @@ int PingInCivCar(int minPingInDist) lane = possibleLanes[(Random2(0) >> 8) % numPossibleLanes]; } + ClearMem((char*)&civDat, sizeof(civDat)); + // check if need to make a parked car if (ROAD_IS_PARKING_ALLOWED_AT(&roadInfo, lane)) { @@ -2209,7 +2147,9 @@ int PingInCivCar(int minPingInDist) // Car is not active. Permanently parked if (ROAD_IS_AI_LANE(&roadInfo, lane) == 0) { +#ifdef DEBUG civPingTest.NotDrivable++; +#endif return 0; } @@ -2312,7 +2252,7 @@ int PingInCivCar(int minPingInDist) } else { - scDist = lbody / 2; + scDist = lbody * 2; minDistAlong = 0; } @@ -2777,221 +2717,198 @@ static u_char hornchanflag[2] = { 0 }; // [D] [T] void SetUpCivCollFlags(void) { - CAR_COSMETICS* car_cos; + CAR_DATA* cp0; CAR_DATA* cp1; + CAR_COSMETICS* car0_cos; + CAR_COSMETICS* car1_cos; SVECTOR boxDisp; - CAR_DATA* cp0; - int carLength[2]; + int cp0Length; + int cp0Computed; int i; - int brake; - int dx; - int extraLength; - int boxOverlap; CDATA2D cd[2]; ClearMem((char*)brakeLength, sizeof(brakeLength)); - cp0 = &car_data[MAX_CARS - 1]; - - while (cp0 >= car_data) + for (cp0 = &car_data[MAX_CARS - 1]; cp0 >= car_data; cp0--) { - if (cp0->controlType == CONTROL_TYPE_CIV_AI) + int extraLength; + int cp0BrakeLength; + + if (cp0->controlType != CONTROL_TYPE_CIV_AI) { - extraLength = FIXEDH(cp0->hd.wheel_speed); + continue; + } - if (cp0->wheel_angle < 61) - extraLength *= 13; - else - extraLength *= 4; + extraLength = FIXEDH(cp0->hd.wheel_speed); - extraLength = ABS(extraLength); + if (cp0->wheel_angle < 61) + extraLength *= 13; + else + extraLength *= 4; - car_cos = cp0->ap.carCos; - carLength[0] = car_cos->colBox.vz; + extraLength = ABS(extraLength); - cd[0].length[0] = carLength[0] + 93 + extraLength; - cd[0].length[1] = car_cos->colBox.vx; - cd[0].theta = cp0->hd.direction; + car0_cos = cp0->ap.carCos; + cp0Length = car0_cos->colBox.vz; - gte_SetRotMatrix(&cp0->hd.where.m); - gte_SetTransMatrix(&cp0->hd.where.m); + cd[0].length[0] = cp0Length + extraLength + 93; + cd[0].x.vx = cp0->hd.where.t[0]; + cd[0].x.vy = cp0->hd.where.t[1]; + cd[0].x.vz = cp0->hd.where.t[2]; - boxDisp.vx = -car_cos->cog.vx; - boxDisp.vy = -car_cos->cog.vy; - boxDisp.vz = (extraLength - car_cos->cog.vz) + 93; + cp0Computed = 0; + cp0BrakeLength = brakeLength[cp0->id]; - gte_ldv0(&boxDisp); - gte_rtv0tr(); - gte_stlvnl(&cd[0].x); + for (cp1 = &car_data[MAX_CARS]; cp1 >= car_data; cp1--) + { + int dist, isTanner; + int brake, boxOverlap; + + if (cp1->controlType == CONTROL_TYPE_NONE || cp1 == cp0) + { + continue; + } - cp1 = &car_data[MAX_CARS]; + car1_cos = cp1->ap.carCos; - while (cp1 >= car_data) + isTanner = 0; + if (CAR_INDEX(cp1) == TANNER_COLLIDER_CARID) { - if (cp1->controlType != CONTROL_TYPE_NONE && cp1 != cp0) + if (player[0].playerType != 2) { - car_cos = cp1->ap.carCos; + continue; + } + + cd[1].length[0] = 60; + cd[1].length[1] = 60; + cd[1].x.vx = player[0].pos[0]; + cd[1].x.vy = player[0].pos[1]; + cd[1].x.vz = player[0].pos[2]; + cd[1].theta = player[0].dir; - if (CAR_INDEX(cp1) == TANNER_COLLIDER_CARID) - { - if (player[0].playerType != 2) - { - cp1--; - continue; - } + isTanner = 1; + } + else + { + cd[1].length[0] = car1_cos->colBox.vz; + cd[1].length[1] = car1_cos->colBox.vx; + cd[1].x.vx = cp1->hd.oBox.location.vx; + cd[1].x.vy = cp1->hd.oBox.location.vy; + cd[1].x.vz = cp1->hd.oBox.location.vz; + cd[1].theta = cp1->hd.direction; + } - cd[1].length[0] = 60; - cd[1].length[1] = 60; - cd[1].x.vx = player[0].pos[0]; - cd[1].x.vz = player[0].pos[2]; - cd[1].theta = player[0].dir; - } - else - { - cd[1].length[0] = car_cos->colBox.vz; - cd[1].length[1] = car_cos->colBox.vx; - cd[1].x.vx = cp1->hd.oBox.location.vx; - cd[1].x.vy = cp1->hd.oBox.location.vy; - cd[1].x.vz = cp1->hd.oBox.location.vz; - cd[1].theta = cp1->hd.direction; - } + dist = ((cd[0].length[0] + cd[1].length[0]) * 3) / 2; - dx = ((cd[0].length[0] + cd[1].length[0]) * 3) / 2; + if (ABS(cd[0].x.vx - cd[1].x.vx) >= dist || + ABS(cd[0].x.vz - cd[1].x.vz) >= dist || + ABS(cd[0].x.vy - cd[1].x.vy) >= 500) + { + continue; + } - if (cd[0].x.vx - cd[1].x.vx < 0) - { - if (cd[1].x.vx - cd[0].x.vx >= dx) - { - cp1--; - continue; - } + if (cp0Computed == 0) + { + cd[0].length[1] = car0_cos->colBox.vx; + cd[0].theta = cp0->hd.direction; - } - else if (dx <= cd[0].x.vx - cd[1].x.vx) - { - cp1--; - continue; - } + gte_SetRotMatrix(&cp0->hd.where.m); + gte_SetTransMatrix(&cp0->hd.where.m); - if (cd[0].x.vz - cd[1].x.vz < 0) - { - if (cd[1].x.vz - cd[0].x.vz >= dx) - { - cp1--; - continue; - } - } - else if (dx <= cd[0].x.vz - cd[1].x.vz) - { - cp1--; - continue; - } + boxDisp.vx = -car0_cos->cog.vx; + boxDisp.vy = -car0_cos->cog.vy; + boxDisp.vz = (extraLength - car0_cos->cog.vz) + 93; - // check height difference - if (CAR_INDEX(cp1) == CAMERA_COLLIDER_CARID) - { - if (ABS(player[0].pos[1] - cp0->hd.where.t[1]) >= 500) - { - cp1--; - continue; - } - } - else if (ABS(cp1->hd.where.t[1] - cp0->hd.where.t[1]) >= 500 && ABS(player[0].pos[1] - cp0->hd.where.t[1]) >= 500) - { - cp1--; - continue; - } + gte_ldv0(&boxDisp); + gte_rtv0tr(); + gte_stlvnl(&cd[0].x); + cp0Computed = 1; + } - // do overlap test between boxes - if (!bcollided2d(cd, &boxOverlap)) - { - cp1--; - continue; - } + // do overlap test between boxes + if (!bcollided2d(cd, &boxOverlap)) + { + continue; + } - brake = (cd[0].length[0] - carLength[0]) - boxOverlap; + brake = MAX(1, (cd[0].length[0] - cp0Length) - boxOverlap); - if (brake < 1) - brake = 1; + if (cp0BrakeLength == 0 || brake < cp0BrakeLength) + { + cp0BrakeLength = brake; + brakeLength[cp0->id] = cp0BrakeLength; + } - if (brakeLength[cp0->id] == 0 || brake < brakeLength[cp0->id]) - brakeLength[cp0->id] = brake; + // don't do anything further when it tries to park + if (cp0->ai.c.thrustState == 3) + { + continue; + } - // don't do anything further when it tries to park - if (cp0->ai.c.thrustState == 3) + // wait for Tanner to get into car + if (isTanner) + { + cp0->ai.c.carPauseCnt = CAR_PAUSE_START; + } + + // do horns + // horn to player and chased cars (except Steal the Ambulance) + if (cp0->ai.c.thrustState != 3 && + (isTanner || cp1->controlType == CONTROL_TYPE_PLAYER || cp1->controlType == CONTROL_TYPE_CUTSCENE && gCurrentMissionNumber != 26 && ProxyBar.active == 0)) + { + int dont; + int rnd; + rnd = Random2(0); + + dont = 0; + + for (i = 0; i < 2; i++) + { + if (horncarflag[i] == cp0) { - cp1--; - continue; + dont = 1; + break; } + } - if (CAR_INDEX(cp1) == TANNER_COLLIDER_CARID) - cp0->ai.c.carPauseCnt = CAR_PAUSE_START; + if (dont) + { + continue; + } - // do horns - // horn to player and chased cars (except Steal the Ambulance) - if (cp0->ai.c.thrustState != 3 && - (cp1->controlType == CONTROL_TYPE_PLAYER || cp1->controlType == CONTROL_TYPE_CUTSCENE && gCurrentMissionNumber != 26 && ProxyBar.active == 0 || - CAR_INDEX(cp1) == TANNER_COLLIDER_CARID)) + for (i = 0; i < 2; i++) + { + if (hornchanflag[i] == 0) { - int dont; - int rnd; - rnd = Random2(0); + int sample; - dont = 0; + hornchanflag[i] = GetFreeChannel(); + SpuSetVoiceAR(hornchanflag[i], 27); - for (i = 0; i < 2; i++) - { - if (horncarflag[i] == cp0) - { - dont = 1; - break; - } - } - - if (dont) - { - cp1--; - continue; - } + if (cp0->ap.model == 4) + sample = ResidentModelsBodge(); + else if (cp0->ap.model < 3) + sample = cp0->ap.model; + else + sample = cp0->ap.model - 1; - for (i = 0; i < 2; i++) - { - if (hornchanflag[i] == 0) - { - int sample; - - hornchanflag[i] = GetFreeChannel(); - SpuSetVoiceAR(hornchanflag[i], 27); - - if (cp0->ap.model == 4) - sample = ResidentModelsBodge(); - else if (cp0->ap.model < 3) - sample = cp0->ap.model; - else - sample = cp0->ap.model - 1; - - // [A] use tracking sound - Start3DTrackingSound(hornchanflag[i], SOUND_BANK_CARS, sample * 3 + 2, - (VECTOR*)cp0->hd.where.t, - (LONGVECTOR3*)cp0->st.n.linearVelocity); + // [A] use tracking sound + Start3DTrackingSound(hornchanflag[i], SOUND_BANK_CARS, sample * 3 + 2, + (VECTOR*)cp0->hd.where.t, + (LONGVECTOR3*)cp0->st.n.linearVelocity); - SetChannelVolume(hornchanflag[i], -2000, 0); + SetChannelVolume(hornchanflag[i], -2000, 0); - horncarflag[i] = cp0; + horncarflag[i] = cp0; - channels[hornchanflag[i]].time += rnd - (rnd / 30) * 30; - break; - } - } + channels[hornchanflag[i]].time += rnd - (rnd / 30) * 30; + break; } } - - cp1--; } - } - cp0--; - } + } // for cp1 + } // for cp0 // clear on timeout for (i = 0; i < 2; i++) @@ -3194,10 +3111,8 @@ int CivFindPointOnPath(CAR_DATA * cp, int station, VECTOR * ppoint) CIV_ROUTE_ENTRY* start; CIV_ROUTE_ENTRY* currentNode; CIV_ROUTE_ENTRY* retNode; - int dx; - int dz; - int sx; - int sz; + int dx, dz; + int sx, sz; start = cp->ai.c.pnode; @@ -3355,18 +3270,16 @@ int CivSteerAngle(CAR_DATA* cp) // [D] [T] void CreateRoadblock(void) { - int laneNo; + VECTOR startPos, endPos, currentPos; + VECTOR baseLoc, randomLoc; CAR_COSMETICS* car_cos; CAR_DATA* cp; - int distAlongSegment; - DRIVER2_CURVE* crv; DRIVER2_STRAIGHT* str; - VECTOR startPos; - VECTOR endPos; - - VECTOR currentPos; + int dx, dz; + int laneNo; + int distAlongSegment; int numLanes; int externalCopModel; int noMoreCars; @@ -3671,9 +3584,12 @@ int CivControl(CAR_DATA* cp) if (cp->ai.c.thrustState != 3) steer = CivSteerAngle(cp); - thrust = CivAccel(cp) - MAX(ABS(steer), 4) * 3; // [A] reduce acceleration when steering is applied - - if (thrust < 0 && cp->hd.wheel_speed < 5) + thrust = CivAccel(cp); + if (thrust != 0) // [A] reduce acceleration when steering is applied + thrust = CivAccel(cp) - MAX(ABS(steer), 4) * 3; + + // [A] fix backwards crawl + if (thrust < 0 && cp->hd.wheel_speed < 100) thrust = 0; cp->wheel_angle = steer; @@ -3681,8 +3597,8 @@ int CivControl(CAR_DATA* cp) #if 0 { - //maxCivCars = 2; - //maxCopCars = 0; + //maxCivCars = 2; + //maxCopCars = 0; extern void Debug_AddLine(VECTOR & pointA, VECTOR & pointB, CVECTOR & color); extern void Debug_AddLineOfs(VECTOR & pointA, VECTOR & pointB, VECTOR & ofs, CVECTOR & color); diff --git a/src_rebuild/Game/C/civ_ai.h b/src_rebuild/Game/C/civ_ai.h index 069ebf00f..91a28aad9 100644 --- a/src_rebuild/Game/C/civ_ai.h +++ b/src_rebuild/Game/C/civ_ai.h @@ -46,7 +46,7 @@ extern void SetUpTrafficLightPhase(); // 0x0002D220 extern int TrafficLightCycle(int exit); // 0x0002CF18 extern int CreateCivCarWotDrivesABitThenStops(int direction, LONGVECTOR4* startPos, LONGVECTOR4* stopPos, unsigned char internalModel, int palette); // 0x000286E0 -extern int CreateStationaryCivCar(int direction, long orientX, long orientZ, LONGVECTOR4* startPos, int externalModel, int palette, int controlFlags); // 0x00028960 +extern int CreateStationaryCivCar(int direction, int orientX, int orientZ, LONGVECTOR4* startPos, int externalModel, int palette, int controlFlags); // 0x00028960 extern int CheckChangeLanes(DRIVER2_STRAIGHT* straight, DRIVER2_CURVE* curve, int distAlongSegment, CAR_DATA* cp, int tryToPark); // 0x00026F20 extern int NotTravellingAlongCurve(int x, int z, int dir, DRIVER2_CURVE* cv); diff --git a/src_rebuild/Game/C/convert.c b/src_rebuild/Game/C/convert.c index 2d8e1ca6f..3c5f24297 100644 --- a/src_rebuild/Game/C/convert.c +++ b/src_rebuild/Game/C/convert.c @@ -183,5 +183,5 @@ extern int frameStart; // [D] [T] int Random2(int step) { - return (CameraCnt - frameStart) * (CameraCnt - frameStart) * 0x19660d + 0x3c6ef35fU >> 8 & 0xffff; + return RAND((CameraCnt - frameStart) * (CameraCnt - frameStart)) >> 8 & 65535; } diff --git a/src_rebuild/Game/C/cop_ai.c b/src_rebuild/Game/C/cop_ai.c index e4b66db11..5607550a6 100644 --- a/src_rebuild/Game/C/cop_ai.c +++ b/src_rebuild/Game/C/cop_ai.c @@ -65,7 +65,7 @@ static int said_picked_up = 0; char last_cop_phrase = 0; -char CopWorkMem[444]; // PVS table +char CopWorkMem[PVS_CELL_COUNT * PVS_CELL_COUNT + 3]; // PVS table COP_SIGHT_DATA copSightData; int player_position_known = 0; @@ -379,6 +379,7 @@ void CopControl1(CAR_DATA *cp) // [A] periodically beat player in ass if (!doBatter && *playerFelony > gCopData.autoBatterPlayerTrigger) { +#if ENABLE_GAME_ENCHANCEMENTS int batterTrigger; if(gCopDifficultyLevel == 0) @@ -393,10 +394,11 @@ void CopControl1(CAR_DATA *cp) cp->ai.p.batterTimer++; cp->ai.p.batterTimer &= 127; +#else + doBatter = 1; +#endif } - - if (cp->ai.p.dying != 0 || cp->totalDamage > 27000 && gCopData.immortal == 0) { @@ -854,7 +856,11 @@ void ControlCopDetection(void) } // [A] also check player elevation from cops (block cops vision from bridges, tunnels etc) - if (spotted && ABS(cp->hd.where.t[1] - vec.vy) < 1000) + if (spotted +#if ENABLE_GAME_ENCHANCEMENTS + && ABS(cp->hd.where.t[1] - vec.vy) < 1000 +#endif + ) { CopsCanSeePlayer = 1; break; @@ -865,6 +871,7 @@ void ControlCopDetection(void) } } +#if ENABLE_GAME_ENCHANCEMENTS // [A] if Tanner is outside car, cops can arrest him if they are too close if(player[0].playerType == 2 && minDistanceToPlayer < 2048 && !player[0].dying && pedestrianFelony > FELONY_PURSUIT_MIN_VALUE) { @@ -873,6 +880,7 @@ void ControlCopDetection(void) SetMissionMessage(G_LTXT(GTXT_YouveBeenCaught),3,2); SetMissionFailed(FAILED_MESSAGESET); } +#endif if (numActiveCops == 0 && OutOfSightCount < 256 && CameraCnt > 8) { diff --git a/src_rebuild/Game/C/cosmetic.c b/src_rebuild/Game/C/cosmetic.c index 44cf49fde..d537efe9c 100644 --- a/src_rebuild/Game/C/cosmetic.c +++ b/src_rebuild/Game/C/cosmetic.c @@ -19,9 +19,29 @@ char* CosmeticFiles[] = { CAR_COSMETICS car_cosmetics[MAX_CAR_MODELS]; +#if ENABLE_GAME_FIXES // [A] storage for spooled models // remember: we already have more than 1k of free memory with optimizations CAR_COSMETICS levelSpecCosmetics[5]; +#endif + +#if USE_PC_FILESYSTEM +extern int gContentOverride; + +// [A] loads car cosmetics from file +void LoadCustomCarCosmetics(CAR_COSMETICS* dest, int modelNumber) +{ + char filename[64]; + + sprintf(filename, "LEVELS\\%s\\CARMODEL_%d.COS", LevelNames[GameLevel], modelNumber); + if (!FileExists(filename)) + { + return; + } + + LoadfileSeg(filename, (char*)dest, 0, sizeof(CAR_COSMETICS)); +} +#endif // [D] [T] void ProcessCosmeticsLump(char *lump_ptr, int lump_size) @@ -47,20 +67,26 @@ void ProcessCosmeticsLump(char *lump_ptr, int lump_size) if (model != -1) { offset = *(int*)(lump_ptr + model * sizeof(int)); - memcpy((u_char*)&car_cosmetics[i], (u_char*)lump_ptr + offset, sizeof(CAR_COSMETICS)); + car_cosmetics[i] = *(CAR_COSMETICS*)((u_char*)lump_ptr + offset); +#if USE_PC_FILESYSTEM + if(gContentOverride) + LoadCustomCarCosmetics(&car_cosmetics[i], model); +#endif FixCarCos(&car_cosmetics[i], model); } } // [A] cache all special vehicle cosmetics +#if ENABLE_GAME_FIXES for (i = 0; i < 5; i++) { model = 8 + i; offset = *(int*)(lump_ptr + model * sizeof(int)); - memcpy((u_char*)&levelSpecCosmetics[i], (u_char*)lump_ptr + offset, sizeof(CAR_COSMETICS)); + levelSpecCosmetics[i] = *(CAR_COSMETICS*)((u_char*)lump_ptr + offset); } +#endif } // [D] [T] @@ -113,11 +139,16 @@ void SetupSpecCosmetics(char *loadbuffer) int model; model = MissionHeader->residentModels[4]; -#if 1 +#if ENABLE_GAME_FIXES // [A] always use cached cosmetics - memcpy((u_char*)&car_cosmetics[4], (u_char*)&levelSpecCosmetics[model - 8], sizeof(CAR_COSMETICS)); + car_cosmetics[4] = levelSpecCosmetics[model - 8]; #else - memcpy((u_char*)&car_cosmetics[4], loadbuffer, sizeof(CAR_COSMETICS)); + car_cosmetics[4] = *(CAR_COSMETICS*)loadbuffer; +#endif + +#if USE_PC_FILESYSTEM + if (gContentOverride) + LoadCustomCarCosmetics(&car_cosmetics[4], model); #endif // [A] don't forget diff --git a/src_rebuild/Game/C/cutrecorder.c b/src_rebuild/Game/C/cutrecorder.c index 85aadd831..44c1acc84 100644 --- a/src_rebuild/Game/C/cutrecorder.c +++ b/src_rebuild/Game/C/cutrecorder.c @@ -564,7 +564,7 @@ int CutRec_LoadCutsceneAsReplayFromBuffer(char* buffer) REPLAY_STREAM* destStream = &ReplayStreams[i]; // copy source type - memcpy((u_char*)&destStream->SourceType, (u_char*)&sheader->SourceType, sizeof(STREAM_SOURCE)); + destStream->SourceType = sheader->SourceType; int size = (sheader->Size + sizeof(PADRECORD)) & -4; diff --git a/src_rebuild/Game/C/cutscene.c b/src_rebuild/Game/C/cutscene.c index 1e5451e4b..5828e9dba 100644 --- a/src_rebuild/Game/C/cutscene.c +++ b/src_rebuild/Game/C/cutscene.c @@ -86,55 +86,6 @@ void FreeCutsceneBuffer(); int IsCutsceneResident(int cutscene); -#ifndef PSX -char gUserReplayFolderList[MAX_USER_REPLAYS][48]; -int gNumUserChases = 0; -int gUserChaseLoaded = -1; - -// [A] user replay folders initialization -void InitUserReplays(const char* str) -{ - int quit; - char* ptr; - char* strStart; - gNumUserChases = 0; - - if (!str) - return; - - ptr = (char*)str; - strStart = NULL; - memset(gUserReplayFolderList, 0, sizeof(gUserReplayFolderList)); - - quit = 0; - - while(true) - { - if (strStart == NULL) - strStart = ptr; - - // if we're encountered string end go on - if(*ptr == ',' || *ptr == ' ' || *ptr == '\0') - { - if (*ptr == '\0') - quit = 1; - - *ptr = '\0'; - strcpy(gUserReplayFolderList[gNumUserChases++], strStart); - strStart = NULL; - } - - ptr++; - - if (quit) - break; - } -} - - -#endif - - // [D] [T] void InitInGameCutsceneVariables(void) { @@ -159,10 +110,6 @@ void InitInGameCutsceneVariables(void) gSkipInGameCutscene = 0; -#ifndef PSX - gUserChaseLoaded = -1; -#endif - FreeCutsceneBuffer(); } @@ -231,23 +178,11 @@ void DrawInGameCutscene(void) TILE *tile; #ifndef PSX - PrintXASubtitles(); + PrintXASubtitles(SCREEN_H - 28); #endif if (gInGameCutsceneActive == 0 && gInGameCutsceneDelay == 0) { -#ifndef PSX - if(gInGameChaseActive && gUserChaseLoaded != -1 && (CameraCnt - frameStart) < 200) - { - // [A] print user chaser name on screen - char tempStr[80]; - - sprintf(tempStr, "%s %s", G_LTXT(GTXT_GetawayIs), gUserReplayFolderList[gUserChaseLoaded]); - - SetTextColour(128, 128, 64); - PrintString(tempStr, gOverlayXPos, 230); - } -#endif return; } @@ -392,34 +327,8 @@ int SelectCutsceneFile(char* filename, int init, int subindex) if (init) { // try load replacement bundle -#ifndef PSX - int userId = -1; - - // [A] REDRIVER2 PC - custom user chases - if (gNumUserChases) - { - userId = rand() % (gNumUserChases + 1); - - // if random decides to have no user chase - get og or replacement one - if (userId == gNumUserChases) - userId = -1; - } - - // try loading user chase - if (userId != -1) - sprintf(filename, "REPLAYS\\UserChases\\%s\\CUT%d_N.R", (char*)gUserReplayFolderList[userId], gCurrentMissionNumber); - - if (FileExists(filename)) - { - gUserChaseLoaded = userId; - gReChaseAvailable = 0; - } - else -#endif - { - sprintf(filename, "REPLAYS\\ReChases\\CUT%d_N.R", gCurrentMissionNumber); - gReChaseAvailable = FileExists(filename); - } + sprintf(filename, "REPLAYS\\ReChases\\CUT%d_N.R", gCurrentMissionNumber); + gReChaseAvailable = FileExists(filename); } if (subindex >= 2) @@ -427,21 +336,14 @@ int SelectCutsceneFile(char* filename, int init, int subindex) if (gReChaseAvailable == 1) { sprintf(filename, "REPLAYS\\ReChases\\CUT%d_N.R", gCurrentMissionNumber); + return FileExists(filename); } -#ifndef PSX - else if (gUserChaseLoaded != -1) - { - sprintf(filename, "REPLAYS\\UserChases\\%s\\CUT%d_N.R", (char*)gUserReplayFolderList[gUserChaseLoaded], gCurrentMissionNumber); - } -#endif } + + if (gCurrentMissionNumber < 21) + sprintf(filename, "REPLAYS\\CUT%d.R", gCurrentMissionNumber); else - { - if (gCurrentMissionNumber < 21) - sprintf(filename, "REPLAYS\\CUT%d.R", gCurrentMissionNumber); - else - sprintf(filename, "REPLAYS\\A\\CUT%d.R", gCurrentMissionNumber); - } + sprintf(filename, "REPLAYS\\A\\CUT%d.R", gCurrentMissionNumber); return FileExists(filename); } @@ -462,7 +364,7 @@ int CalcInGameCutsceneSize(void) LoadfileSeg(filename, (char*)&CutsceneHeader, 0, sizeof(CUTSCENE_HEADER)); // load re-chase file header - if(SelectCutsceneFile(filename, 0, 2)) + if (SelectCutsceneFile(filename, 0, 2)) LoadfileSeg(filename, (char*)&ChaseHeader, 0, sizeof(CUTSCENE_HEADER)); maxSize = 0; @@ -502,7 +404,7 @@ void ReleaseInGameCutscene(void) { if (PlayerStartInfo[i]->flags & 4) { - memcpy((u_char*)&player[0], (u_char*)&player[i], sizeof(PLAYER)); + player[0] = player[i]; if (player[0].playerType == 2) { @@ -916,13 +818,14 @@ int LoadCutsceneToReplayBuffer(int residentCutscene) // add to existing replay streams for (int i = NumReplayStreams; i < (NumReplayStreams + rheader->NumReplayStreams); i++) { + int size; sheader = (REPLAY_STREAM_HEADER *)pt; pt += sizeof(REPLAY_STREAM_HEADER); REPLAY_STREAM* destStream = &ReplayStreams[i]; // copy source type - memcpy((u_char*)&destStream->SourceType, (u_char*)&sheader->SourceType, sizeof(STREAM_SOURCE)); + destStream->SourceType = sheader->SourceType; // init buffers destStream->InitialPadRecordBuffer = (PADRECORD*)replayptr; @@ -932,7 +835,7 @@ int LoadCutsceneToReplayBuffer(int residentCutscene) destStream->length = sheader->Length; destStream->playbackrun = 0; - int size = (sheader->Size + sizeof(PADRECORD)) & -4; + size = (sheader->Size + sizeof(PADRECORD)) & -4; // copy pad data and advance buffer memcpy((u_char*)replayptr, (u_char*)pt, size); diff --git a/src_rebuild/Game/C/cutscene.h b/src_rebuild/Game/C/cutscene.h index 535314247..20fa8b74a 100644 --- a/src_rebuild/Game/C/cutscene.h +++ b/src_rebuild/Game/C/cutscene.h @@ -13,16 +13,6 @@ struct CUTSCENE_HEADER CUTSCENE_INFO data[15]; }; -#ifndef PSX -#define MAX_USER_REPLAYS 16 - -extern char gUserReplayFolderList[MAX_USER_REPLAYS][48]; -extern int gNumUserChases; - -extern void InitUserReplays(const char* str); - -#endif // PSX - extern int NumCutsceneStreams; extern int gSkipInGameCutscene; extern int gInGameCutsceneID; diff --git a/src_rebuild/Game/C/debris.c b/src_rebuild/Game/C/debris.c index 0765a8048..2c3833f1b 100644 --- a/src_rebuild/Game/C/debris.c +++ b/src_rebuild/Game/C/debris.c @@ -401,6 +401,8 @@ DAMAGED_LAMP damaged_lamp[MAX_DAMAGED_LAMPS]; MATRIX debris_mat; MATRIX leaf_mat; +#define LAMP_STREAK_ID(x,y) (((x) & 0xffff) | (((y) & 0xffff) << 16)) + // [D] [T] void PlacePoolForCar(CAR_DATA *cp, CVECTOR *col, int front, int in_car) { @@ -735,11 +737,11 @@ void AddLeaf(VECTOR *Position, int num_leaves, int Type) } // apply colors - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { *(u_int*)&myleaf->rgb = *(u_int*)&myleaf->rgb >> 2 & 0x3f3f3f3f; } - else if (gWeather == 1 || gWeather == 2) + else if (gWeather == WEATHER_RAIN || gWeather == WEATHER_WET) { *(u_int*)&myleaf->rgb = *(u_int*)&myleaf->rgb >> 1 & 0x7f7f7f7f; } @@ -815,26 +817,26 @@ void InitDebrisNames(void) GetTextureDetails("FOREARM1", &forearm1_texture); GetTextureDetails("CHEST1", &chest1_texture); GetTextureDetails("LOWHEAD", &head1_texture); - GetTextureDetails("ADDCAM", &addcam); - GetTextureDetails("FRAMEADV", &frameadv); - GetTextureDetails("AUTO", &autocam); - GetTextureDetails("CHASEC", &chasecar); - GetTextureDetails("CHOOSECA", &choosecar); - GetTextureDetails("CLOCK", &clock); - GetTextureDetails("DELCAM", &delcam); - GetTextureDetails("EDITCAM", &editcam); - GetTextureDetails("FIXEDCA", &fixedcam); - GetTextureDetails("INCAR", &incar); - GetTextureDetails("LENSCHA", &lenschan); - GetTextureDetails("LOOKCAR", &lookcar); - GetTextureDetails("MOVECMP", &movecam); - GetTextureDetails("MOVECAM", &movecampos); - GetTextureDetails("OK", &ok); - GetTextureDetails("PAUSE", &pause); - GetTextureDetails("PLAYCAM", &playcam); - GetTextureDetails("PLAYPAU", &playpause); - GetTextureDetails("SAVE2CA", &save2card); - GetTextureDetails("RESTREP", &restart); + GetTextureDetails("ADDCAM", &icon_addcam); + GetTextureDetails("FRAMEADV", &icon_frameadv); + GetTextureDetails("AUTO", &icon_autocam); + GetTextureDetails("CHASEC", &icon_chasecar); + GetTextureDetails("CHOOSECA", &icon_choosecar); + GetTextureDetails("CLOCK", &icon_clock); + GetTextureDetails("DELCAM", &icon_delcam); + GetTextureDetails("EDITCAM", &icon_editcam); + GetTextureDetails("FIXEDCA", &icon_fixedcam); + GetTextureDetails("INCAR", &icon_incar); + GetTextureDetails("LENSCHA", &icon_lenschan); + GetTextureDetails("LOOKCAR", &icon_lookcar); + GetTextureDetails("MOVECMP", &icon_movecam); + GetTextureDetails("MOVECAM", &icon_movecampos); + GetTextureDetails("OK", &icon_ok); + GetTextureDetails("PAUSE", &icon_pause); + GetTextureDetails("PLAYCAM", &icon_playcam); + GetTextureDetails("PLAYPAU", &icon_playpause); + GetTextureDetails("SAVE2CA", &icon_save2card); + GetTextureDetails("RESTREP", &icon_restart); GetTextureDetails("HEAD1", &texturePedHead); GetTextureDetails("TSHADOW", &tannerShadow_texture); @@ -1092,7 +1094,7 @@ void DrawSmashable_sprites(void) { UNIMPLEMENTED(); - if (gWeather - 1U < 2 || gTimeOfDay == 3) + if (gWeather - 1U < 2 || gTimeOfDay == TIME_NIGHT) { plotContext.colour = NightAmbient << 0x10 | NightAmbient << 8 | NightAmbient | 0x2c000000; } @@ -1257,21 +1259,18 @@ int find_lamp_streak(int LampId) return -1; } + + // [D] [T] void AddSmallStreetLight(CELL_OBJECT *cop, int x, int y, int z, int type) { int count; DAMAGED_LAMP* dam; int halo_size; - short size; - short angle; - VECTOR v1; - VECTOR v2; - VECTOR v3; - SVECTOR pos; - CVECTOR col; - CVECTOR col1; - SVECTOR dpos; + short size, angle; + VECTOR v1, v2, v3; + SVECTOR pos, dpos; + CVECTOR col, col1; dam = damaged_lamp; col = {140, 140, 140}; @@ -1296,7 +1295,8 @@ void AddSmallStreetLight(CELL_OBJECT *cop, int x, int y, int z, int type) } count = 0; - do { + for(count = 0; count < 4; count++) + { if (dam->index == cop->pos.vx + cop->pos.vz) { if (dam->damage > 2) @@ -1308,10 +1308,8 @@ void AddSmallStreetLight(CELL_OBJECT *cop, int x, int y, int z, int type) break; } - - count++; dam++; - } while (count < 4); + } dpos.vx = cop->pos.vx - camera_position.vx; dpos.vy = cop->pos.vy - camera_position.vy; @@ -1371,7 +1369,7 @@ void AddSmallStreetLight(CELL_OBJECT *cop, int x, int y, int z, int type) v3 = v1; - LightIndex = find_lamp_streak(cop->pos.vx + cop->pos.vz + x); // [A] was pointer. + LightIndex = find_lamp_streak(LAMP_STREAK_ID(cop->pos.vx + x, cop->pos.vz)); // [A] was pointer. if (LightIndex > -1) col.cd = 0x60; @@ -1381,6 +1379,10 @@ void AddSmallStreetLight(CELL_OBJECT *cop, int x, int y, int z, int type) DisplayLightReflections(&v2, &col1, halo_size * 2, &lightref_texture); +#ifdef DYNAMIC_LIGHTING + AddDlight(&v3, &col, size * 280 >> 4); +#endif // DYNAMIC_LIGHTING + LightSortCorrect = -10; } @@ -1390,8 +1392,7 @@ void AddLightEffect(CELL_OBJECT *cop, int x, int y, int z, int type, int colour) short yang; int angle; int size; - VECTOR v1; - VECTOR v2; + VECTOR v1, v2; VECTOR dpos; SVECTOR pos; CVECTOR col; @@ -1503,6 +1504,11 @@ void AddLightEffect(CELL_OBJECT *cop, int x, int y, int z, int type, int colour) gte_SetTransVector(&v1); ShowLight1(&v1, &col, size, &light_texture); + +#ifdef DYNAMIC_LIGHTING + AddDlight(&v1, &col, size * 180 >> 4); +#endif // DYNAMIC_LIGHTING + DisplayLightReflections(&v2, &col, (size << 0xd) >> 0x10, &lightref_texture); } @@ -1748,6 +1754,7 @@ void AddTrafficLight(CELL_OBJECT *cop, int x, int y, int z, int flag, int yang) v2.vx = v1.vx; v2.vz = v1.vz; + v2.vy = v1.vy; v2.vy = -camera_position.vy - MapHeight((VECTOR*)&cop->pos); if (gNight) @@ -1767,7 +1774,7 @@ void AddTrafficLight(CELL_OBJECT *cop, int x, int y, int z, int flag, int yang) a.g = (a.g * tempfade) >> 10; LightSortCorrect = -140; - LightIndex = find_lamp_streak(cop->pos.vx + cop->pos.vz + x + y); // [A] was pointer. + LightIndex = find_lamp_streak(LAMP_STREAK_ID(cop->pos.vx + x, cop->pos.vz + y)); // [A] was pointer. if (LightIndex < 0) a.cd = 0; @@ -2027,18 +2034,17 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture) if (z < 0) z = 0; - if (z < 10000) - tail_width = (10000 - z) >> 0xd; - else - tail_width = 0; - addPrim(current->ot + z, poly); current->primptr += sizeof(POLY_FT4); - if (CameraCnt <= 4 || NumPlayers > 1) // [A] don't draw trails in multiplayer return; + if (z < 10000) + tail_width = (10000 - z) >> 13; + else + return; + if ((col->cd & 0x20) && gLightsOn) { trails = Known_Lamps[LightIndex].light_trails; @@ -2066,15 +2072,15 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture) } #ifndef PSX - x = (poly->x0 + poly->x3) / 2.0f; - y = (poly->y0 + poly->y3) / 2.0f; + x = (poly->x0 + poly->x3) * 0.5f; + y = (poly->y0 + poly->y3) * 0.5f; #else x = (poly->x0 + poly->x3) / 2; y = (poly->y0 + poly->y3) / 2; #endif // unified drawing both for car and lamps - if (CameraChanged == 0 && *clock == (FrameCnt & 0xffffU)-1) + if (CameraChanged == 0 && *clock == (FrameCnt & 0xffffU) - 1) { int old_x, old_y; @@ -2087,7 +2093,11 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture) if (size > 1 && ABS(old_x - x) + ABS(old_y - y) > 1) { int angle, width; - VERTTYPE dx, dy; +#ifdef PSX + int dx, dy; +#else + float dx, dy; +#endif trail = (POLY_G4 *)current->primptr; @@ -2097,21 +2107,20 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture) angle = -ratan2(old_x - x,old_y - y) & 0xfff; width = ABS(poly->x0 - poly->x3); -#ifdef PSX dx = RCOS(angle) * width * 3; dy = RSIN(angle) * width * 3; - + if (col->cd & 0x40) { - dx >>= 0x10; - dy >>= 0x10; + dx /= 1 << 16; + dy /= 1 << 16; } else { - dx >>= 0xf; - dy >>= 0xf; + dx /= 1 << 15; + dy /= 1 << 15; } - + trail->x0 = x + dx * tail_width; trail->y0 = y + dy * tail_width; @@ -2123,34 +2132,6 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture) trail->x3 = old_x - dx; trail->y3 = old_y - dy; -#else - // [A] slightly bigger light trail - dx = RCOS(angle); - dy = RSIN(angle); - - if (col->cd & 0x40) - { - dx = dx / 40000.0f; - dy = dy / 40000.0f; - } - else - { - dx = dx / 32768.0f; - dy = dy / 32768.0f; - } - - trail->x0 = x + dx * width * 3 * tail_width; - trail->y0 = y + dy * width * 3 * tail_width; - - trail->x1 = x - dx * width * 3 * tail_width; - trail->y1 = y - dy * width * 3 * tail_width; - - trail->x2 = old_x + dx * width * 3; - trail->y2 = old_y + dy * width * 3; - - trail->x3 = old_x - dx * width * 3; - trail->y3 = old_y - dy * width * 3; -#endif if (col->cd & 0x18) { @@ -2185,8 +2166,8 @@ void ShowLight(VECTOR *v1, CVECTOR *col, short size, TEXTURE_DETAILS *texture) addPrim(current->ot + z, null); current->primptr += sizeof(POLY_FT3); - } } + } else { for (i = 0; i < 4; i++) @@ -2461,7 +2442,7 @@ void DisplaySpark(SMOKE *spark) { colorind = spark->drift.vy * 3 & 3; - if (gTimeOfDay == 1) + if (gTimeOfDay == TIME_DAY) { poly->r0 = grassColour[colorind][0]; poly->g0 = grassColour[colorind][1]; @@ -2578,7 +2559,7 @@ void Setup_Debris(VECTOR *ipos, VECTOR *ispeed, int num_debris, int type) mydebris->rgb.g = debris_colour[GameLevel][col].g; mydebris->rgb.b = debris_colour[GameLevel][col].b; - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { mydebris->rgb.r >>= 1; mydebris->rgb.g >>= 1; @@ -3472,43 +3453,49 @@ void DisplaySplashes(void) if (pauseflag != 0) return; - if (gRainCount >> 2 > 30) + SplashNo = gRainCount >> 1; + + if (SplashNo > 30) SplashNo = 30; - else - SplashNo = (gRainCount >> 2); SplashFrac = FIXEDH(SplashNo * FrAng * 3); gte_SetRotMatrix(&identity); // [A] norot CamGnd.vx = camera_position.vx; + CamGnd.vy = camera_position.vy; CamGnd.vz = camera_position.vz; + CamGnd.vy = -camera_position.vy - MapHeight(&CamGnd); ang = FrAng - camera_angle.vy; + + Gnd1.vx = (RSIN(ang) >> 1) + camera_position.vx; + Gnd1.vy = CamGnd.vy; + Gnd1.vz = (RCOS(ang) >> 1) + camera_position.vz; - Gnd1.vx = RSIN(ang) + camera_position.vx; - Gnd1.vz = RCOS(ang) + camera_position.vz; - - Gnd1.vx = Gnd1.vx - CamGnd.vx; - Gnd1.vy = -camera_position.vy - MapHeight(&Gnd1) - CamGnd.vy; - Gnd1.vz = Gnd1.vz - CamGnd.vz; + Gnd1.vy = -camera_position.vy - MapHeight(&Gnd1); + Gnd1.vx -= CamGnd.vx; + Gnd1.vy -= CamGnd.vy; + Gnd1.vz -= CamGnd.vz; ang = -FrAng - camera_angle.vy; - Gnd2.vx = RSIN(ang) + camera_position.vx; - Gnd2.vz = RCOS(ang) + camera_position.vz; + Gnd2.vx = (RSIN(ang) >> 1) + camera_position.vx; + Gnd2.vy = CamGnd.vy; + Gnd2.vz = (RCOS(ang) >> 1) + camera_position.vz; - Gnd2.vx = Gnd2.vx - CamGnd.vx; - Gnd2.vy = (-camera_position.vy - MapHeight(&Gnd2)) - CamGnd.vy; - Gnd2.vz = Gnd2.vz - CamGnd.vz; + Gnd2.vy = -camera_position.vy - MapHeight(&Gnd2); + Gnd2.vx -= CamGnd.vx; + Gnd2.vy -= CamGnd.vy; + Gnd2.vz -= CamGnd.vz; while (--SplashFrac >= 0) { - d2 = rand * 0x19660d + 0x3c6ef35f; - d1 = d2 >> 4 & 0xfff; - rand = d2 * 0x19660d + 0x3c6ef35f; - d2 = rand >> 0xe & 0xfff; + d2 = RAND(rand); + d1 = d2 >> 4 & 4095; + rand = RAND(d2); + d2 = rand >> 14 & 4095; Position.vx = FIXEDH(Gnd1.vx * d1 + Gnd2.vx * d2); Position.vy = FIXEDH(Gnd1.vy * d1 + Gnd2.vy * d2) + CamGnd.vy; @@ -3582,7 +3569,6 @@ void DrawRainDrops(void) RainPtr->position.vy += RAIN_DROP_SPEED; RainPtr->position.vx -= drift.vx * 2; RainPtr->position.vz -= drift.vz * 2; - *(u_int *)&poly->x0 = *(u_int *)&RainPtr->oldposition; } @@ -3625,10 +3611,9 @@ void DrawRainDrops(void) else *(u_int *)&RainPtr->oldposition = *(u_int *)&poly->x2; } - else + else if (pauseflag == 0) { - if(pauseflag == 0) - ReleaseRainDrop(RainPtr->oldposition.pad); + ReleaseRainDrop(RainPtr->oldposition.pad); } RainPtr++; @@ -3677,14 +3662,14 @@ void AddRainDrops(void) if (RainIndex < 0) return; - tmp = rand * 0x19660d + 0x3c6ef35f; - v.vz = (tmp >> 0x14 & 0x1ffU) + 400; + tmp = RAND(rand); + v.vz = (tmp >> 20 & 511) + 400; - tmp = tmp * 0x19660d + 0x3c6ef35f; - v.vy = -((tmp >> 0x14) & 0x1ff); + tmp = RAND(tmp); + v.vy = -((tmp >> 20) & 511); - rand = tmp * 0x19660d + 0x3c6ef35f; - v.vx = ((rand >> 0x14) & 0x1ff) - 256; + rand = RAND(tmp); + v.vx = ((rand >> 20) & 511) - 256; if (v.vz > 512) { @@ -3805,7 +3790,7 @@ void DoThunder(void) // [D] [T] void DoWeather(int weather) { - if (weather != 1) + if (weather != WEATHER_RAIN) return; if(pauseflag == 0) diff --git a/src_rebuild/Game/C/denting.c b/src_rebuild/Game/C/denting.c index 82bf54edf..cb3926ffe 100644 --- a/src_rebuild/Game/C/denting.c +++ b/src_rebuild/Game/C/denting.c @@ -12,6 +12,29 @@ #include "players.h" #include "main.h" +#if USE_PC_FILESYSTEM +extern int gContentOverride; + +// [A] loads car model from file +char* LoadCustomCarDentingFromFile(char* dest, int modelNumber) +{ + char* mem; + char filename[64]; + + sprintf(filename, "LEVELS\\%s\\CARMODEL_%d.DEN", LevelNames[GameLevel], modelNumber); + if (FileExists(filename)) + { + mem = dest ? dest : ((char*)_other_buffer + modelNumber * 4096); + + // get model from file + Loadfile(filename, mem); + return mem; + } + + return NULL; +} +#endif + char* DentingFiles[] = { "LEVELS\\CHICAGO.DEN", @@ -28,7 +51,7 @@ char* DentingFiles[] = u_char gCarDamageZoneVerts[MAX_CAR_MODELS][NUM_DAMAGE_ZONES][MAX_DAMAGE_ZONE_VERTS]; u_char gHDCarDamageZonePolys[MAX_CAR_MODELS][NUM_DAMAGE_ZONES][MAX_DAMAGE_ZONE_POLYS]; -u_char gHDCarDamageLevels[MAX_CAR_MODELS][MAX_DAMAGE_LEVELS]; +u_char gHDCarDamageLevels[MAX_CAR_MODELS][MAX_DAMAGE_LEVELS]; // the damage level (texture) count for polygons // [D] [T] void InitialiseDenting(void) @@ -66,12 +89,11 @@ void DentCar(CAR_DATA *cp) // collect vertices from zones if (pCleanModel != NULL) { - VertNo = 0; - while (VertNo < pCleanModel->num_vertices) - tempDamage[VertNo++] = 0; + for (VertNo = 0; VertNo < pCleanModel->num_vertices; VertNo++) + tempDamage[VertNo] = 0; - Zone = 0; - do { + for (Zone = 0; Zone < NUM_DAMAGE_ZONES; Zone++) + { Damage = cp->ap.damage[Zone]; if (Damage > MaxDamage) @@ -79,21 +101,14 @@ void DentCar(CAR_DATA *cp) DamPtr = gCarDamageZoneVerts[cp->ap.model][Zone]; - VertNo = 0; - while (VertNo < MAX_DAMAGE_ZONE_VERTS && *DamPtr != 0xFF) + for (VertNo = 0; VertNo < MAX_DAMAGE_ZONE_VERTS && *DamPtr != 0xFF; VertNo++, DamPtr++) { if (tempDamage[*DamPtr] == 0) tempDamage[*DamPtr] += Damage; else tempDamage[*DamPtr] += Damage / 2; - - DamPtr++; - - VertNo++; } - - Zone++; - } while (Zone < NUM_DAMAGE_ZONES); + } } // update vertices positon @@ -102,17 +117,11 @@ void DentCar(CAR_DATA *cp) DamVertPtr = (SVECTOR *)gCarDamModelPtr[model]->vertices; CleanVertPtr = (SVECTOR *)gCarCleanModelPtr[model]->vertices; - VertNo = 0; - while (VertNo < pCleanModel->num_vertices) + for (VertNo = 0; VertNo < pCleanModel->num_vertices; VertNo++, DamVertPtr++, CleanVertPtr++) { gTempCarVertDump[cp->id][VertNo].vx = CleanVertPtr->vx + FIXEDH((DamVertPtr->vx - CleanVertPtr->vx) * tempDamage[VertNo] / 2); gTempCarVertDump[cp->id][VertNo].vy = CleanVertPtr->vy + FIXEDH((DamVertPtr->vy - CleanVertPtr->vy) * tempDamage[VertNo] / 2); gTempCarVertDump[cp->id][VertNo].vz = CleanVertPtr->vz + FIXEDH((DamVertPtr->vz - CleanVertPtr->vz) * tempDamage[VertNo] / 2); - - DamVertPtr++; - CleanVertPtr++; - - VertNo++; } } @@ -122,21 +131,22 @@ void DentCar(CAR_DATA *cp) dentptr = gTempHDCarUVDump[cp->id]; // reset UV coordinates - Poly = 0; - while (Poly < pCleanModel->num_polys) + + for (Poly = 0; Poly < pCleanModel->num_polys; Poly++) { dentptr->u3 = 0; - Poly++; dentptr++; } - Zone = 0; - do { + for(Zone = 0; Zone < NUM_DAMAGE_ZONES; Zone++) + { Damage = cp->ap.damage[Zone]; - Poly = 0; - while (Poly < MAX_DAMAGE_ZONE_POLYS && gHDCarDamageZonePolys[cp->ap.model][Zone][Poly] != 0xFF) + for (Poly = 0; Poly < MAX_DAMAGE_ZONE_POLYS; Poly++) { + if (gHDCarDamageZonePolys[cp->ap.model][Zone][Poly] == 0xFF) + break; + dentptr = gTempHDCarUVDump[cp->id] + gHDCarDamageZonePolys[cp->ap.model][Zone][Poly]; // add a damage level @@ -145,28 +155,17 @@ void DentCar(CAR_DATA *cp) // clamp level if (dentptr->u3 > 2) dentptr->u3 = 2; - - Poly++; } - - Zone++; - } while (Zone < NUM_DAMAGE_ZONES); - - Poly = 0; + } DamPtr = gHDCarDamageLevels[model]; dentptr = gTempHDCarUVDump[cp->id]; - while (Poly < pCleanModel->num_polys) + for (Poly = 0; Poly < pCleanModel->num_polys; Poly++, DamPtr++, dentptr++) { // calculate the UV offset with strange XORs if(dentptr->u3 > 0) dentptr->u3 = (*DamPtr ^ 1 ^ (*DamPtr ^ 1 | dentptr->u3)) * 64; - - dentptr++; - - DamPtr++; - Poly++; } } } @@ -194,11 +193,9 @@ void CreateDentableCar(CAR_DATA *cp) while (vcount-- != -1) *dst++ = *src++; - count = 0; - while (count < srcModel->num_polys) + for (count = 0; count < srcModel->num_polys; count++) { gTempHDCarUVDump[cp->id][count].u3 = 0; - count++; } } else @@ -209,11 +206,9 @@ void CreateDentableCar(CAR_DATA *cp) srcModel = gCarLowModelPtr[model]; if (srcModel != NULL) { - count = 0; - while (count < srcModel->num_polys) + for (count = 0; count < srcModel->num_polys; count++) { gTempLDCarUVDump[cp->id][count].u3 = 0; - count++; } } else @@ -223,11 +218,9 @@ void CreateDentableCar(CAR_DATA *cp) if (gDontResetCarDamage == 0) { - count = 0; - while (count < NUM_DAMAGE_ZONES) + for (count = 0; count < NUM_DAMAGE_ZONES; count++) { cp->ap.damage[count] = 0; - count++; } cp->totalDamage = 0; @@ -392,7 +385,7 @@ void MoveHubcap() _MatrixRotate(&Position); savecombo = combointensity; - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { cmb = (combointensity & 0xffU) / 3; combointensity = cmb << 0x10 | cmb << 8 | cmb; @@ -407,27 +400,6 @@ void MoveHubcap() } } -#ifndef PSX -// [A] loads car model from file -char* LoadCarDentingFromFile(char* dest, int modelNumber) -{ - char* mem; - char filename[64]; - - sprintf(filename, "LEVELS\\%s\\CARMODEL_%d.DEN", LevelNames[GameLevel], modelNumber); - if(FileExists(filename)) - { - mem = dest ? dest : ((char*)_other_buffer + modelNumber * 4096); - - // get model from file - Loadfile(filename, mem); - return mem; - } - - return NULL; -} -#endif - // [D] [T] void ProcessDentLump(char *lump_ptr, int lump_size) { @@ -436,9 +408,7 @@ void ProcessDentLump(char *lump_ptr, int lump_size) int offset; u_char* mem; - i = 0; - - while (i < MAX_CAR_MODELS) + for (i = 0; i < MAX_CAR_MODELS; i++) { model = MissionHeader->residentModels[i]; @@ -456,12 +426,16 @@ void ProcessDentLump(char *lump_ptr, int lump_size) { offset = *(int *)(lump_ptr + model * 4); mem = (u_char*)lump_ptr; -#ifndef PSX - char* newDenting = LoadCarDentingFromFile(NULL, model); - if(newDenting) +#if USE_PC_FILESYSTEM + if (gContentOverride) { - mem = (u_char*)newDenting; - offset = 0; + char* newDenting; + newDenting = LoadCustomCarDentingFromFile(NULL, model); + if (newDenting) + { + mem = (u_char*)newDenting; + offset = 0; + } } #endif @@ -473,8 +447,6 @@ void ProcessDentLump(char *lump_ptr, int lump_size) memcpy((u_char*)gHDCarDamageLevels[i], mem + offset, MAX_FILE_DAMAGE_LEVELS); } - - i++; } } @@ -484,6 +456,20 @@ void SetupSpecDenting(char *loadbuffer) { int offset; +#if USE_PC_FILESYSTEM + if (gContentOverride) + { + char* newDenting; + int model; + model = MissionHeader->residentModels[4]; + + newDenting = LoadCustomCarDentingFromFile(NULL, model); + if (newDenting) + loadbuffer = newDenting; + } + +#endif + // [A] this is better memcpy((u_char*)gCarDamageZoneVerts[4], (u_char*)loadbuffer, NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_VERTS); offset = NUM_DAMAGE_ZONES * MAX_FILE_DAMAGE_ZONE_VERTS; diff --git a/src_rebuild/Game/C/director.c b/src_rebuild/Game/C/director.c index e7b836683..22d8448b0 100644 --- a/src_rebuild/Game/C/director.c +++ b/src_rebuild/Game/C/director.c @@ -27,52 +27,52 @@ struct REPLAY_ICON short tx, ty; }; -TEXTURE_DETAILS delcam; // address 0xC0EE0 -TEXTURE_DETAILS incar; // address 0xBF950 -TEXTURE_DETAILS lenschan; // address 0xC1DB0 -TEXTURE_DETAILS lookcar; // address 0xC1CB0 -TEXTURE_DETAILS movecam; // address 0xC1C18 -TEXTURE_DETAILS movecampos; // address 0xC08C0 -TEXTURE_DETAILS ok; // address 0xC1BD8 -TEXTURE_DETAILS pause; // address 0xBF970 -TEXTURE_DETAILS playpause; // address 0xC2A28 -TEXTURE_DETAILS clock; // address 0xBF940 -TEXTURE_DETAILS choosecar; // address 0xC2A08 -TEXTURE_DETAILS chasecar; // address 0xC1D60 -TEXTURE_DETAILS addcam; // address 0xC0A50 -TEXTURE_DETAILS autocam; // address 0xC1CA0 -TEXTURE_DETAILS playcam; // address 0xC1C08 -TEXTURE_DETAILS restart; // address 0xC1CD0 -TEXTURE_DETAILS save2card; // address 0xC1F40 -TEXTURE_DETAILS editcam; // address 0xC1BE8 -TEXTURE_DETAILS fixedcam; // address 0xC1D70 -TEXTURE_DETAILS frameadv; // address 0xC1D80 +TEXTURE_DETAILS icon_delcam; // address 0xC0EE0 +TEXTURE_DETAILS icon_incar; // address 0xBF950 +TEXTURE_DETAILS icon_lenschan; // address 0xC1DB0 +TEXTURE_DETAILS icon_lookcar; // address 0xC1CB0 +TEXTURE_DETAILS icon_movecam; // address 0xC1C18 +TEXTURE_DETAILS icon_movecampos; // address 0xC08C0 +TEXTURE_DETAILS icon_ok; // address 0xC1BD8 +TEXTURE_DETAILS icon_pause; // address 0xBF970 +TEXTURE_DETAILS icon_playpause; // address 0xC2A28 +TEXTURE_DETAILS icon_clock; // address 0xBF940 +TEXTURE_DETAILS icon_choosecar; // address 0xC2A08 +TEXTURE_DETAILS icon_chasecar; // address 0xC1D60 +TEXTURE_DETAILS icon_addcam; // address 0xC0A50 +TEXTURE_DETAILS icon_autocam; // address 0xC1CA0 +TEXTURE_DETAILS icon_playcam; // address 0xC1C08 +TEXTURE_DETAILS icon_restart; // address 0xC1CD0 +TEXTURE_DETAILS icon_save2card; // address 0xC1F40 +TEXTURE_DETAILS icon_editcam; // address 0xC1BE8 +TEXTURE_DETAILS icon_fixedcam; // address 0xC1D70 +TEXTURE_DETAILS icon_frameadv; // address 0xC1D80 REPLAY_ICON replay_icons[] = { - { 20, 26, &pause, G_LTXT_ID(GTXT_Pause), 20, 48 }, - { 20, 26, &playpause, G_LTXT_ID(GTXT_Play), 20, 48 }, - { 44, 26, &autocam, G_LTXT_ID(GTXT_AutoDirector), 44, 48 }, - { 68, 26, &playcam, G_LTXT_ID(GTXT_FastForward), 68, 48 }, - { 92, 26, &frameadv, G_LTXT_ID(GTXT_FrameAdvance), 92, 48 }, - { 116, 26, &restart, G_LTXT_ID(GTXT_Rewindtobeginning), 116, 48 }, - { 140, 26, &addcam, G_LTXT_ID(GTXT_AddCamera), 140, 48 }, - { 164, 26, &editcam, G_LTXT_ID(GTXT_EditCamera), 164, 48 }, - { 188, 26, &save2card, G_LTXT_ID(GTXT_SaveReplay), 188, 48 }, - { 212, 26, &ok, G_LTXT_ID(GTXT_Exit), 212, 48 }, - { 140, 50, &incar, G_LTXT_ID(GTXT_InCar), 164, 48 }, - { 140, 74, &chasecar, G_LTXT_ID(GTXT_ChaseCamera), 164, 72 }, - { 140, 98, &fixedcam, G_LTXT_ID(GTXT_TripodCamera), 164, 96 }, - { 140, 122, &ok, G_LTXT_ID(GTXT_Accept), 164, 120 }, - { 140, 122, &clock, G_LTXT_ID(GTXT_MoveCameraStart), 164, 120 }, - { 140, 146, &delcam, G_LTXT_ID(GTXT_DeleteCamera), 164, 144 }, - { 140, 170, &ok, G_LTXT_ID(GTXT_Accept), 164, 168 }, - { 164, 50, &choosecar, G_LTXT_ID(GTXT_YouorPursuer), 164, 72 }, - { 164, 74, &movecampos, G_LTXT_ID(GTXT_MoveCamera), 164, 96 }, - { 164, 98, &movecampos, G_LTXT_ID(GTXT_MoveCamera), 164, 120 }, - { 188, 98, &lookcar, G_LTXT_ID(GTXT_LocktoCar), 188, 120 }, - { 212, 98, &movecam, G_LTXT_ID(GTXT_Rotate), 212, 120 }, - { 236, 98, &lenschan, G_LTXT_ID(GTXT_Zoom), 236, 120 } + { 20, 26, &icon_pause, G_LTXT_ID(GTXT_Pause), 20, 48 }, + { 20, 26, &icon_playpause, G_LTXT_ID(GTXT_Play), 20, 48 }, + { 44, 26, &icon_autocam, G_LTXT_ID(GTXT_AutoDirector), 44, 48 }, + { 68, 26, &icon_playcam, G_LTXT_ID(GTXT_FastForward), 68, 48 }, + { 92, 26, &icon_frameadv, G_LTXT_ID(GTXT_FrameAdvance), 92, 48 }, + { 116, 26, &icon_restart, G_LTXT_ID(GTXT_Rewindtobeginning), 116, 48 }, + { 140, 26, &icon_addcam, G_LTXT_ID(GTXT_AddCamera), 140, 48 }, + { 164, 26, &icon_editcam, G_LTXT_ID(GTXT_EditCamera), 164, 48 }, + { 188, 26, &icon_save2card, G_LTXT_ID(GTXT_SaveReplay), 188, 48 }, + { 212, 26, &icon_ok, G_LTXT_ID(GTXT_Exit), 212, 48 }, + { 140, 50, &icon_incar, G_LTXT_ID(GTXT_InCar), 164, 48 }, + { 140, 74, &icon_chasecar, G_LTXT_ID(GTXT_ChaseCamera), 164, 72 }, + { 140, 98, &icon_fixedcam, G_LTXT_ID(GTXT_TripodCamera), 164, 96 }, + { 140, 122, &icon_ok, G_LTXT_ID(GTXT_Accept), 164, 120 }, + { 140, 122, &icon_clock, G_LTXT_ID(GTXT_MoveCameraStart), 164, 120 }, + { 140, 146, &icon_delcam, G_LTXT_ID(GTXT_DeleteCamera), 164, 144 }, + { 140, 170, &icon_ok, G_LTXT_ID(GTXT_Accept), 164, 168 }, + { 164, 50, &icon_choosecar, G_LTXT_ID(GTXT_YouorPursuer), 164, 72 }, + { 164, 74, &icon_movecampos, G_LTXT_ID(GTXT_MoveCamera), 164, 96 }, + { 164, 98, &icon_movecampos, G_LTXT_ID(GTXT_MoveCamera), 164, 120 }, + { 188, 98, &icon_lookcar, G_LTXT_ID(GTXT_LocktoCar), 188, 120 }, + { 212, 98, &icon_movecam, G_LTXT_ID(GTXT_Rotate), 212, 120 }, + { 236, 98, &icon_lenschan, G_LTXT_ID(GTXT_Zoom), 236, 120 } }; unsigned char menu0[] = { 0, 0xFF }; diff --git a/src_rebuild/Game/C/director.h b/src_rebuild/Game/C/director.h index 3aa6219f7..4432dae0e 100644 --- a/src_rebuild/Game/C/director.h +++ b/src_rebuild/Game/C/director.h @@ -1,26 +1,26 @@ #ifndef DIRECTOR_H #define DIRECTOR_H -extern TEXTURE_DETAILS addcam; -extern TEXTURE_DETAILS frameadv; -extern TEXTURE_DETAILS autocam; -extern TEXTURE_DETAILS chasecar; -extern TEXTURE_DETAILS choosecar; -extern TEXTURE_DETAILS clock; -extern TEXTURE_DETAILS delcam; -extern TEXTURE_DETAILS editcam; -extern TEXTURE_DETAILS fixedcam; -extern TEXTURE_DETAILS incar; -extern TEXTURE_DETAILS lenschan; -extern TEXTURE_DETAILS lookcar; -extern TEXTURE_DETAILS movecam; -extern TEXTURE_DETAILS movecampos; -extern TEXTURE_DETAILS ok; -extern TEXTURE_DETAILS pause; -extern TEXTURE_DETAILS playcam; -extern TEXTURE_DETAILS playpause; -extern TEXTURE_DETAILS save2card; -extern TEXTURE_DETAILS restart; +extern TEXTURE_DETAILS icon_addcam; +extern TEXTURE_DETAILS icon_frameadv; +extern TEXTURE_DETAILS icon_autocam; +extern TEXTURE_DETAILS icon_chasecar; +extern TEXTURE_DETAILS icon_choosecar; +extern TEXTURE_DETAILS icon_clock; +extern TEXTURE_DETAILS icon_delcam; +extern TEXTURE_DETAILS icon_editcam; +extern TEXTURE_DETAILS icon_fixedcam; +extern TEXTURE_DETAILS icon_incar; +extern TEXTURE_DETAILS icon_lenschan; +extern TEXTURE_DETAILS icon_lookcar; +extern TEXTURE_DETAILS icon_movecam; +extern TEXTURE_DETAILS icon_movecampos; +extern TEXTURE_DETAILS icon_ok; +extern TEXTURE_DETAILS icon_pause; +extern TEXTURE_DETAILS icon_playcam; +extern TEXTURE_DETAILS icon_playpause; +extern TEXTURE_DETAILS icon_save2card; +extern TEXTURE_DETAILS icon_restart; extern int FastForward; extern int EditMode; diff --git a/src_rebuild/Game/C/dr2roads.c b/src_rebuild/Game/C/dr2roads.c index 236d0f902..bade3a62b 100644 --- a/src_rebuild/Game/C/dr2roads.c +++ b/src_rebuild/Game/C/dr2roads.c @@ -5,7 +5,6 @@ #include "map.h" #include "event.h" #include "convert.h" -#include "cutscene.h" #include "mission.h" #include "handling.h" #include "main.h" @@ -102,7 +101,7 @@ int GetSurfaceRoadInfo(DRIVER2_ROAD_INFO* outRoadInfo, int surfId) if(IS_CURVED_SURFACE(surfId)) { outRoadInfo->curve = curve = GET_CURVE(surfId); - outRoadInfo->ConnectIdx = &curve->ConnectIdx; + outRoadInfo->ConnectIdx = curve->ConnectIdx; outRoadInfo->NumLanes = curve->NumLanes; outRoadInfo->LaneDirs = curve->LaneDirs; outRoadInfo->AILanes = curve->AILanes; @@ -111,7 +110,7 @@ int GetSurfaceRoadInfo(DRIVER2_ROAD_INFO* outRoadInfo, int surfId) else if (IS_STRAIGHT_SURFACE(surfId)) { outRoadInfo->straight = straight = GET_STRAIGHT(surfId); - outRoadInfo->ConnectIdx = &straight->ConnectIdx; + outRoadInfo->ConnectIdx = straight->ConnectIdx; outRoadInfo->NumLanes = straight->NumLanes; outRoadInfo->LaneDirs = straight->LaneDirs; outRoadInfo->AILanes = straight->AILanes; @@ -120,7 +119,7 @@ int GetSurfaceRoadInfo(DRIVER2_ROAD_INFO* outRoadInfo, int surfId) else if (IS_JUNCTION_SURFACE(surfId)) { junction = GET_JUNCTION(surfId); - outRoadInfo->ConnectIdx = &junction->ExitIdx; + outRoadInfo->ConnectIdx = junction->ExitIdx; } return 0; @@ -204,11 +203,13 @@ void ProcessStraightsDriver2Lump(char *lump_file, int lump_size) } else if (GameLevel == 2) { +#if ENABLE_GAME_FIXES int i; DRIVER2_STRAIGHT* str; Driver2StraightsPtr[348].ConnectIdx[2] = 8244; Driver2StraightsPtr[348].ConnectIdx[3] = 351; +#endif } } @@ -348,71 +349,71 @@ sdPlane* sdGetCell(VECTOR *pos) // Alpha 1.6 code, works too; not widely tested yet //buffer = *(short**)((int)RoadMapDataRegions + (cellPos.x >> 14 & 4 ^ cellPos.y >> 13 & 8 ^ sdSelfModifyingCode)); - plane = NULL; + plane = GetSeaPlane(); - if (*buffer == 2) - { - sdPlane* planeData = (sdPlane*)((char*)buffer + buffer[1]); - short* bspData = (short*)((char*)buffer + buffer[2]); - sdNode* nodeData = (sdNode*)((char*)buffer + buffer[3]); + if (*buffer != 2) + return &default_plane; + + sdPlane* planeData = (sdPlane*)((char*)buffer + buffer[1]); + short* bspData = (short*)((char*)buffer + buffer[2]); + sdNode* nodeData = (sdNode*)((char*)buffer + buffer[3]); - surface = &buffer[(cellPos.x >> 10 & 63) + - (cellPos.y >> 10 & 63) * 64 + 4]; + surface = &buffer[(cellPos.x >> 10 & 63) + + (cellPos.y >> 10 & 63) * 64 + 4]; - // initial surface - if (*surface == -1) - return GetSeaPlane(); + // initial surface + if (*surface == -1) + return plane; - // check surface has overlapping planes flag (aka multiple levels) - if ((*surface & 0x6000) == 0x2000) - { - surface = &bspData[*surface & 0x1fff]; - do { - if(-256 - pos->vy > *surface) - { - surface += 2; - sdLevel++; - } - else - break; - } while (*surface != -0x8000); // end flag + // check surface has overlapping planes flag (aka multiple levels) + if ((*surface & 0x6000) == 0x2000) + { + surface = &bspData[*surface & 0x1fff]; + do { + if(-256 - pos->vy > *surface) + { + surface += 2; + sdLevel++; + } + else + break; + } while (*surface != -0x8000); // end flag - surface += 1; - } + surface += 1; + } - // iterate surfaces if BSP - do { - nextLevel = 0; + // iterate surfaces if BSP + do { + nextLevel = 0; - // check if it's has BSP properties - // basically it determines surface bounds - if (*surface & 0x4000) - { - // get closest surface by BSP lookup - BSPSurface = sdGetBSP(&nodeData[*surface & 0x3fff], &cell); + // check if it's has BSP properties + // basically it determines surface bounds + if (*surface & 0x4000) + { + // get closest surface by BSP lookup + BSPSurface = sdGetBSP(&nodeData[*surface & 0x3fff], &cell); - if (*BSPSurface == 0x7fff) - { - sdLevel++; - nextLevel = 1; + if (*BSPSurface == 0x7fff) + { + sdLevel++; + nextLevel = 1; - BSPSurface = surface + 2; // get to the next node - } - - surface = BSPSurface; + BSPSurface = surface + 2; // get to the next node } - } while (nextLevel); - plane = &planeData[*surface]; - - if (((int)plane & 3) == 0 && *(int *)plane != -1) - { - if (plane->surface - 16U < 16) - plane = EventSurface(pos, plane); + surface = BSPSurface; } - else - plane = GetSeaPlane(); + } while (nextLevel); + + plane = &planeData[*surface]; + + if (((int)plane & 3) == 0 && *(int *)plane != -1) + { + if (plane->surface - 16U < 16) + plane = EventSurface(pos, plane); } + else + plane = GetSeaPlane(); return plane; } @@ -433,7 +434,7 @@ sdPlane * FindRoadInBSP(sdNode *node, sdPlane *base) { sdPlane *plane; - while (true) + do { if (node->value > -1) { @@ -442,12 +443,8 @@ sdPlane * FindRoadInBSP(sdNode *node, sdPlane *base) } plane = FindRoadInBSP(node + 1, base); - - if (plane != NULL) - break; - node += node->n.offset; - } + } while (plane == NULL); return plane; } @@ -550,14 +547,17 @@ int MapHeight(VECTOR *pos) } // [D] [T] -int FindSurfaceD2(VECTOR *pos, VECTOR *normal, VECTOR *out, sdPlane **plane) +void FindSurfaceD2(VECTOR *pos, VECTOR *normal, VECTOR *out, sdPlane **plane) { - *plane = sdGetCell(pos); + sdPlane* pl; + pl = sdGetCell(pos); + + *plane = pl; out->vx = pos->vx; out->vz = pos->vz; - out->vy = sdHeightOnPlane(pos, *plane); + out->vy = sdHeightOnPlane(pos, pl); - if (*plane == NULL || (*plane)->b == 0) + if (pl == NULL || pl->b == 0) { normal->vx = 0; normal->vy = 4096; @@ -565,24 +565,8 @@ int FindSurfaceD2(VECTOR *pos, VECTOR *normal, VECTOR *out, sdPlane **plane) } else { - normal->vx = (int)(*plane)->a >> 2; - normal->vy = (int)(*plane)->b >> 2; - normal->vz = (int)(*plane)->c >> 2; - } - - if (*plane == NULL) - { - return 4096; + normal->vx = (int)pl->a >> 2; + normal->vy = (int)pl->b >> 2; + normal->vz = (int)pl->c >> 2; } - else if ((*plane)->surface == 4) - { - if (gInGameCutsceneActive && gCurrentMissionNumber == 23 && gInGameCutsceneID == 0) - out->vy += RSIN((pos->vx + pos->vz) * 2) >> 9; // rcossin_tbl[(pos->vx + pos->vz) * 4 & 0x1fff] >> 9; - else - out->vy += (RSIN((pos->vx + pos->vz) * 2) >> 8) / 3; // (rcossin_tbl[(pos->vx + pos->vz) * 4 & 0x1fff] >> 8) / 3; - - return 2048; - } - - return 4096; } \ No newline at end of file diff --git a/src_rebuild/Game/C/dr2roads.h b/src_rebuild/Game/C/dr2roads.h index c989e26b8..27bdb39d4 100644 --- a/src_rebuild/Game/C/dr2roads.h +++ b/src_rebuild/Game/C/dr2roads.h @@ -12,20 +12,25 @@ #define GET_CURVE(surfid) (Driver2CurvesPtr + ((surfid) & 0x1FFF)) #define GET_JUNCTION(surfid) (Driver2JunctionsPtr + ((surfid) & 0x1FFF)) +// AI lanes - each bit represents lane being enabled for Civ AI to be driven +// Lane dirs - each bit represents lane direction invertion +// NumLanes - | Lane count (4 bits - max 15) | speed limit id (2 bits - max 3) | Leftmost Lane parking | Rightmost Lane parking + // $DEPRECATED: as it's used to detect lane direction, use ROAD_LANE_DIR instead #define IS_NARROW_ROAD(rd) \ ((*(ushort*)&(rd)->NumLanes & 0xFFFF) == 0xFF01) // those macros can be applied to straights and junctions -#define ROAD_LANES_COUNT(rd) ((u_int)(rd)->NumLanes & 0xF) // lane count -#define ROAD_WIDTH_IN_LANES(rd) (ROAD_LANES_COUNT(rd) * 2) // width in lanes -#define ROAD_IS_AI_LANE(rd, lane) ((u_char)(rd)->AILanes >> ((lane) / 2) & 1U) // lane AI driveable flag -#define ROAD_IS_LEFTMOST_LANE_PARKING(rd) (((u_char)(rd)->NumLanes & 0x40) != 0) // allows parking on leftmost lane -#define ROAD_IS_RIGHTMOST_LANE_PARKING(rd) (((u_char)(rd)->NumLanes & 0x80) != 0) // allows parking on rightmost lane -#define ROAD_LANE_DIRECTION_BIT(rd, lane) ((u_char)(rd)->LaneDirs >> ((lane) / 2) & 1U) // direction bit -#define ROAD_SPEED_LIMIT(rd) (((u_char)(rd)->NumLanes >> 4) & 3) // speed limit id -#define ROAD_HAS_FAST_LANES(rd) (((u_char)(rd)->NumLanes >> 6) & 1) // & 0x20; in fact speed limit check too +#define ROAD_IS_AI_LANE(rd, lane) ((u_char)(rd)->AILanes >> ((lane) / 2) & 1U) // lane AI driveable flag +#define ROAD_LANE_DIRECTION_BIT(rd, lane) ((u_char)(rd)->LaneDirs >> ((lane) / 2) & 1U) // direction bit + +#define ROAD_LANES_COUNT(rd) ((u_int)(rd)->NumLanes & 15) // lane count +#define ROAD_WIDTH_IN_LANES(rd) (ROAD_LANES_COUNT(rd) * 2) // width in lanes + +#define ROAD_IS_LEFTMOST_LANE_PARKING(rd) (((u_char)(rd)->NumLanes & 0x40) != 0) // bit 7 allows parking on leftmost lane +#define ROAD_IS_RIGHTMOST_LANE_PARKING(rd) (((u_char)(rd)->NumLanes & 0x80) != 0) // bit 8 allows parking on rightmost lane +#define ROAD_SPEED_LIMIT(rd) (((u_char)(rd)->NumLanes >> 4) & 3) // speed limit id #define ROAD_LANE_DIR(rd, lane) \ (((u_char)(rd)->LaneDirs == 0xFF && (rd)->NumLanes == 1) ? ((lane) & 1) : ROAD_LANE_DIRECTION_BIT(rd, lane)) @@ -38,7 +43,7 @@ struct DRIVER2_ROAD_INFO { int surfId; - short (*ConnectIdx)[4]; + short* ConnectIdx; // [4] char NumLanes; char LaneDirs; char AILanes; @@ -75,7 +80,7 @@ extern void ProcessJunctionsDriver2Lump(char *lump_file, int lump_size, int fix) extern int MapHeight(VECTOR *pos); // 0x000137CC -extern int FindSurfaceD2(VECTOR *pos, VECTOR *normal, VECTOR *out, sdPlane **plane); // 0x00012EF4 +extern void FindSurfaceD2(VECTOR *pos, VECTOR *normal, VECTOR *out, sdPlane **plane); // 0x00012EF4 extern int GetSurfaceIndex(VECTOR *pos); // 0x0001380C extern int RoadInCell(VECTOR *pos); // 0x0001322C diff --git a/src_rebuild/Game/C/draw.c b/src_rebuild/Game/C/draw.c index e5756978e..4a02c713a 100644 --- a/src_rebuild/Game/C/draw.c +++ b/src_rebuild/Game/C/draw.c @@ -16,6 +16,9 @@ #include "ASM/rndrasm.h" #include "event.h" +#ifdef PSX +#pragma GCC optimization ("O3") +#endif MATRIX aspect = { @@ -91,26 +94,26 @@ void* model_tile_ptrs[MAX_DRAWN_TILES]; void* anim_obj_buffer[MAX_DRAWN_ANIMATING]; void* spriteList[MAX_DRAWN_SPRITES]; -u_int planeColours[8]; - MATRIX inv_camera_matrix; MATRIX face_camera; MATRIX2 CompoundMatrix[64]; u_int farClip2Player = 36000; +#ifdef PSX +int goFaster = 1; +#else int goFaster = 0; // [A] was 1 +#endif int fasterToggle = 0; -//int current_object_computed_value = 0; - int combointensity; -char CurrentPVS[444]; // 20*20+4 +char CurrentPVS[PVS_CELL_COUNT * PVS_CELL_COUNT + 3]; // 20*20+4 MATRIX2 matrixtable[64]; int setupYet = 0; -int gDrawDistance = 441; +int gDrawDistance = PVS_CELL_COUNT * PVS_CELL_COUNT; #ifndef PSX _pct& plotContext = *(_pct*)((u_char*)getScratchAddr(0) + 1024 - sizeof(_pct)); // orig offset: 0x1f800020 @@ -136,8 +139,8 @@ void addSubdivSpriteShadow(POLYFT4* src, SVECTOR* verts, int z) plotContext.colour = 0x2E000000; plotContext.flags = PLOT_INV_CULL; - plotContext.clut = texture_cluts[src->texture_set][src->texture_id] << 0x10; - plotContext.tpage = texture_pages[src->texture_set] << 0x10; + plotContext.clut = texture_cluts[src->texture_set][src->texture_id]; + plotContext.tpage = texture_pages[src->texture_set]; if (z > 3200) m = 1; //2; @@ -162,9 +165,6 @@ void addSubdivSpriteShadow(POLYFT4* src, SVECTOR* verts, int z) plotContext.ot -= 28; } - -MATRIX shadowMatrix; - // [D] [T] [A] void DrawSprites(PACKED_CELL_OBJECT** sprites, int numFound) { @@ -179,30 +179,26 @@ void DrawSprites(PACKED_CELL_OBJECT** sprites, int numFound) #if 0 //def PSX MVERTEX5x5& subdiVerts = *(MVERTEX5x5*)(u_char*)getScratchAddr(0); + MATRIX shadowMatrix = *(MATRIX*)((u_char*)getScratchAddr(0) + sizeof(MVERTEX5x5)); #else MVERTEX5x5 subdiVerts; + MATRIX shadowMatrix; #endif + SVECTOR* lightVec; - lightdd = FIXEDH(camera_matrix.m[2][0] * day_vectors[GameLevel].vx) + - FIXEDH(camera_matrix.m[2][1] * day_vectors[GameLevel].vy) + - FIXEDH(camera_matrix.m[2][2] * day_vectors[GameLevel].vz) + ONE * 3072; + lightVec = (gTimeOfDay == TIME_NIGHT) ? night_vectors : day_vectors; - lightLevel = (lightdd >> 0x12) + 0x20U & 0xff; + lightdd = FIXEDH(camera_matrix.m[2][0] * lightVec[GameLevel].vx) + + FIXEDH(camera_matrix.m[2][1] * lightVec[GameLevel].vy) + + FIXEDH(camera_matrix.m[2][2] * lightVec[GameLevel].vz) + ONE * 3072; - if (gWeather > 0 && gTimeOfDay == 1) - { - lightLevel = (lightLevel * 2 * NightAmbient) >> 8 & 0xff; - } + lightLevel = (lightdd >> 18) + 32 & 255; - if (gTimeOfDay == 0) - { - lightLevel = (lightLevel * 2 * NightAmbient) >> 8; - } - else if (gTimeOfDay == 2) + if (gWeather > WEATHER_NONE && gTimeOfDay == TIME_DAY || (M_BIT(gTimeOfDay) & (M_BIT(TIME_DAWN) | M_BIT(TIME_DUSK)))) { lightLevel = (lightLevel * 2 * NightAmbient) >> 8; } - else if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { if (GameLevel == 0) lightLevel *= 2; // [A] level bug - Chicago trees lit wrong @@ -210,43 +206,44 @@ void DrawSprites(PACKED_CELL_OBJECT** sprites, int numFound) lightLevel /= 3; } - spriteColour = lightLevel << 0x10 | lightLevel << 8 | 0x2c000000 | lightLevel; + spriteColour = lightLevel << 0x10 | lightLevel << 8 | lightLevel | 0x2c000000; - i = 2; - do { + for (i = 0; i < 3; i++) + { shadowMatrix.m[i][0] = inv_camera_matrix.m[i][2]; shadowMatrix.m[i][1] = -inv_camera_matrix.m[i][0]; shadowMatrix.m[i][2] = inv_camera_matrix.m[i][0]; - } while (i--); - + } plotContext.primptr = current->primptr; plotContext.ptexture_pages = (ushort(*)[128])texture_pages; plotContext.ptexture_cluts = (ushort(*)[128][32])texture_cluts; plotContext.polySizes = PolySizes; plotContext.ot = current->ot; - - list = sprites; - plotContext.colour = spriteColour; plotContext.current = current; + list = sprites; numShadows = 0; while (numFound--) { + int modelnumber; pco = *list; list++; - int modelnumber = (pco->value >> 6) | (pco->pos.vy & 1) << 10; - + modelnumber = (pco->value >> 6) | (pco->pos.vy & 1) << 10; model = modelpointers[modelnumber]; - plotContext.colour = spriteColour; -#ifndef PSX - if ((pco->value & 0x3f) == 63 || (gTimeOfDay == 3 && modelnumber == 945)) // [A] Vegas tree fix + if ((pco->value & 63) == 63 || litSprites[modelnumber >> 5] & 1 << (modelnumber & 31)) // [A] multiple sprites lighting fixes + { plotContext.colour = 0x2c808080; -#endif + } + else + { + plotContext.colour = spriteColour; + } + plotContext.scribble[0] = pco->pos.vx; plotContext.scribble[1] = (pco->pos.vy << 0x10) >> 0x11; plotContext.scribble[2] = pco->pos.vz; @@ -263,12 +260,12 @@ void DrawSprites(PACKED_CELL_OBJECT** sprites, int numFound) src = (POLYFT4*)model->poly_block; verts = (SVECTOR*)model->vertices; - plotContext.flags |= 4; + plotContext.flags |= PLOT_NO_CULL; while (numPolys--, numPolys >= 0) { - plotContext.clut = texture_cluts[src->texture_set][src->texture_id] << 0x10; - plotContext.tpage = texture_pages[src->texture_set] << 0x10; + plotContext.clut = texture_cluts[src->texture_set][src->texture_id]; + plotContext.tpage = texture_pages[src->texture_set]; copyVector(&subdiVerts.verts[0][0], &verts[src->v0]); subdiVerts.verts[0][0].uv.val = *(ushort*)&src->uv0; @@ -288,7 +285,7 @@ void DrawSprites(PACKED_CELL_OBJECT** sprites, int numFound) src++; } - plotContext.flags &= ~4; + plotContext.flags &= ~PLOT_NO_CULL; } else { @@ -305,8 +302,8 @@ void DrawSprites(PACKED_CELL_OBJECT** sprites, int numFound) #define MAX_TREE_SHADOW_DISTANCE 14000 #endif - if (wetness == 0 && gTimeOfDay != 3 && - (pco->value & 0x20) == 0 && + if (wetness == 0 && gTimeOfDay != TIME_NIGHT && + (pco->value & 32) == 0 && z < MAX_TREE_SHADOW_DISTANCE && numShadows < 40) { @@ -330,76 +327,86 @@ void SetupPlaneColours(u_int ambient) { u_int r, g, b; - if ((gWeather - 1U > 1) && gTimeOfDay != 0 && gTimeOfDay != 2) + if (gWeather == 0 && (M_BIT(gTimeOfDay) & (M_BIT(TIME_DAWN) | M_BIT(TIME_DUSK))) == 0) { - if (gTimeOfDay == 1) + if (gTimeOfDay == TIME_DAY) { - b = ambient & 0xff; - g = ambient >> 8 & 0xff; - r = ambient >> 0x10 & 0xff; - - planeColours[1] = (r * 0x78 >> 7) << 0x10 | (g * 0x78 >> 7) << 8 | b * 0x78 >> 7; - planeColours[2] = (r * 0x67 >> 7) << 0x10 | (g * 0x67 >> 7) << 8 | b * 0x67 >> 7; - planeColours[3] = (r * 0xd >> 5) << 0x10 | (g * 0xd >> 5) << 8 | b * 0xd >> 5; - planeColours[0] = r << 0x10 | g << 8 | b; - planeColours[4] = (r * 3 >> 3) << 0x10 | (g * 3 >> 3) << 8 | b * 3 >> 3; - planeColours[5] = planeColours[3]; - planeColours[6] = planeColours[2]; - planeColours[7] = planeColours[1]; + b = ambient & 255; + g = ambient >> 8 & 255; + r = ambient >> 16 & 255; + + plotContext.planeColours[1] = (r * 120 >> 7) << 16 | (g * 120 >> 7) << 8 | b * 120 >> 7; + plotContext.planeColours[2] = (r * 103 >> 7) << 16 | (g * 103 >> 7) << 8 | b * 103 >> 7; + plotContext.planeColours[3] = (r * 13 >> 5) << 16 | (g * 13 >> 5) << 8 | b * 13 >> 5; + plotContext.planeColours[0] = r << 16 | g << 8 | b; + plotContext.planeColours[4] = (r * 3 >> 3) << 16 | (g * 3 >> 3) << 8 | b * 3 >> 3; + plotContext.planeColours[5] = plotContext.planeColours[3]; + plotContext.planeColours[6] = plotContext.planeColours[2]; + plotContext.planeColours[7] = plotContext.planeColours[1]; return; } - planeColours[0] = ambient; - planeColours[1] = ambient; - planeColours[2] = ambient; - planeColours[3] = ambient; - planeColours[4] = ambient; - planeColours[5] = ambient; - planeColours[6] = ambient; - planeColours[7] = ambient; + plotContext.planeColours[0] = ambient; + plotContext.planeColours[1] = ambient; + plotContext.planeColours[2] = ambient; + plotContext.planeColours[3] = ambient; + plotContext.planeColours[4] = ambient; + plotContext.planeColours[5] = ambient; + plotContext.planeColours[6] = ambient; + plotContext.planeColours[7] = ambient; return; } - planeColours[0] = ambient; - planeColours[1] = ambient + 0x10101; - planeColours[2] = ambient + 0x30303; - planeColours[3] = ambient + 0x80808; - planeColours[4] = ambient + 0xa0a0a; - planeColours[5] = ambient + 0x80808; - planeColours[6] = ambient + 0x30303; - planeColours[7] = ambient + 0x10101; + plotContext.planeColours[0] = ambient; + plotContext.planeColours[1] = ambient + 0x10101; + plotContext.planeColours[2] = ambient + 0x30303; + plotContext.planeColours[3] = ambient + 0x80808; + plotContext.planeColours[4] = ambient + 0xa0a0a; + plotContext.planeColours[5] = ambient + 0x80808; + plotContext.planeColours[6] = ambient + 0x30303; + plotContext.planeColours[7] = ambient + 0x10101; } +int current_pvs_cell; + + // [D] [T] void SetupDrawMapPSX(void) { - int region_x1; - int region_z1; - int current_barrel_region_x1; - int current_barrel_region_z1; + int cell_x, cell_z; int theta; + int pvs_cell; if (setupYet != 0) + { return; + } + + cell_x = (camera_position.vx + units_across_halved) / MAP_CELL_SIZE; + cell_z = (camera_position.vz + units_down_halved) / MAP_CELL_SIZE; - current_cell_x = (camera_position.vx + units_across_halved) / MAP_CELL_SIZE; - current_cell_z = (camera_position.vz + units_down_halved) / MAP_CELL_SIZE; + current_cell_x = cell_x; + current_cell_z = cell_z; - region_x1 = current_cell_x / MAP_REGION_SIZE; - region_z1 = current_cell_z / MAP_REGION_SIZE; + pvs_cell = (cell_z % MAP_REGION_SIZE) * MAP_REGION_SIZE + (cell_x % MAP_REGION_SIZE); + if (pvs_cell != current_pvs_cell) + { + int region_x1, region_z1; + int current_barrel_region_x1, current_barrel_region_z1; - current_barrel_region_x1 = (region_x1 & 1); - current_barrel_region_z1 = (region_z1 & 1); + region_x1 = cell_x / MAP_REGION_SIZE; + region_z1 = cell_z / MAP_REGION_SIZE; - GetPVSRegionCell2( - current_barrel_region_x1 + current_barrel_region_z1 * 2, - region_x1 + region_z1 * regions_across, - (current_cell_z % MAP_REGION_SIZE) * MAP_REGION_SIZE + (current_cell_x % MAP_REGION_SIZE), - CurrentPVS); + current_barrel_region_x1 = (region_x1 & 1); + current_barrel_region_z1 = (region_z1 & 1); - for (theta = 0; theta < 64; theta++) - MulMatrix0(&inv_camera_matrix, (MATRIX*)&matrixtable[theta], (MATRIX*)&CompoundMatrix[theta]); + current_pvs_cell = pvs_cell; + GetPVSRegionCell2( + current_barrel_region_x1 + current_barrel_region_z1 * 2, + region_x1 + region_z1 * regions_across, + pvs_cell, CurrentPVS); + } InitFrustrumMatrix(); SetFrustrumMatrix(); @@ -412,7 +419,7 @@ MATRIX frustrum_matrix; // [D] [T] void InitFrustrumMatrix(void) { - int a; + int a, t; a = -camera_angle.vy; @@ -431,7 +438,6 @@ void InitFrustrumMatrix(void) frustrum_matrix.m[2][1] = 0; frustrum_matrix.m[2][0] = RSIN(a); frustrum_matrix.m[2][2] = RCOS(a); - frustrum_matrix.t[0] = -80; } // [D] [T] @@ -474,6 +480,12 @@ void PlotMDL_less_than_128(MODEL* model) RenderModel(model, NULL, NULL, 0, 0, 0, 0); } +// [D] [T] +int PositionVisible(VECTOR* pos) +{ + return newPositionVisible(pos, CurrentPVS, current_cell_x, current_cell_z); +} + int gForceLowDetailCars = 0; int num_cars_drawn = 0; @@ -508,7 +520,7 @@ void DrawAllTheCars(int view) else dist = dx + dz / 2; - if (dist < 16000) + if (dist < VIEW_DRAW_DISTANCE) { car_distance[num_cars_to_draw] = dx + dz; cars_to_draw[num_cars_to_draw] = cp; @@ -523,36 +535,28 @@ void DrawAllTheCars(int view) { gForceLowDetailCars = 0; - // sort cars by distance - i = 1; - while (i < num_cars_to_draw) + // insertion sort of cars by distance + for (i = 1; i < num_cars_to_draw; i++) { cp = cars_to_draw[i]; dist = car_distance[i]; j = i - 1; - while (dist < car_distance[j]) + while (j >= 0 && dist < car_distance[j]) { car_distance[i] = car_distance[j]; cars_to_draw[i] = cars_to_draw[j]; - - if (j == 0) - break; - j--; } - cars_to_draw[i] = cp; - car_distance[i] = dist; - - i++; + cars_to_draw[j+1] = cp; + car_distance[j+1] = dist; } - i = 0; spacefree = (num_cars_to_draw - 1) * 2000; - while (i < num_cars_to_draw) + for (i = 0; i < num_cars_to_draw; i++) { // Don't exceed draw buffers if ((int)(current->primtab + (-3000 - (int)(current->primptr - PRIMTAB_SIZE))) < 5800) @@ -568,7 +572,6 @@ void DrawAllTheCars(int view) DrawCar(cars_to_draw[i], view); spacefree -= 2000; - i++; } } } @@ -585,9 +588,9 @@ u_int normalIndex(SVECTOR* verts, u_int vidx) SVECTOR p, q; - v0 = verts + (vidx & 0xff); - v1 = verts + (vidx >> 8 & 0xff); - v2 = verts + (vidx >> 16 & 0xff); + v0 = verts + (vidx & 255); + v1 = verts + (vidx >> 8 & 255); + v2 = verts + (vidx >> 16 & 255); p.vz = v1->vz - v0->vz; q.vz = v2->vz - v0->vz; @@ -618,7 +621,7 @@ u_int normalIndex(SVECTOR* verts, u_int vidx) if (x + y < 1) th23 = x < 0 ? 6 : 7; else - th23 = 0 < y ? 1 : 0; + th23 = y > 0 ? 1 : 0; } th23 *= 4; @@ -632,9 +635,9 @@ u_int normalIndex(SVECTOR* verts, u_int vidx) th23 += 1; if (nx + nz < -ny) - th23 = th23 & 0x1f | 2; + th23 = th23 & 31 | 2; else - th23 = th23 & 0x1f; + th23 = th23 & 31; return th23 | 0x80; } @@ -648,12 +651,12 @@ void ConvertPolygonTypes(MODEL* model, _pct* pc) int i; // [A] we are storing the processing flag here - if (model->tri_verts & 0x8000) + if (model->tri_verts & 0x80) { return; } - model->tri_verts |= 0x8000; + model->tri_verts |= 0x80; srcVerts = (SVECTOR*)model->vertices; polys = (PL_POLYFT4*)model->poly_block; @@ -662,10 +665,10 @@ void ConvertPolygonTypes(MODEL* model, _pct* pc) // pre-process vertices while (i-- > 0) { - ptype = polys->id & 0x1f; + ptype = polys->id & 31; // convert poly types - if ((ptype & 0x1) == 0 && ptype != 8) // is FT3 triangle? + if ((ptype & 1) == 0 && ptype != 8) // is FT3 triangle? { temp = polys->uv2.v; polys->uv3.u = polys->uv2.u; @@ -709,10 +712,12 @@ void PlotBuildingModel(MODEL* model, int rot, _pct* pc) ConvertPolygonTypes(model, pc); + r = (rot >> 3) * 4; + i = model->num_polys; while (i-- > 0) { - ptype = polys->id & 0x1f; + ptype = polys->id & 31; // skip certain polygons if (ptype != 11 && ptype != 21 && ptype != 23) @@ -729,15 +734,13 @@ void PlotBuildingModel(MODEL* model, int rot, _pct* pc) gte_nclip(); gte_stopz(&opz); - r = rot; - if (ptype == 21) { - pc->colour = combo & 0x2ffffffU | 0x2c000000; + pc->colour = combo & 0x2ffffff | 0x2c000000; } else { - pc->colour = pc->f4colourTable[(r >> 3) * 4 - polys->th & 31]; + pc->colour = pc->f4colourTable[r - polys->th & 31]; } if (opz > 0) @@ -804,12 +807,14 @@ void PlotBuildingModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) ConvertPolygonTypes(model, pc); + r = (rot >> 3) * 4; + i = model->num_polys; while (i-- > 0) { // iterate through polygons // with skipping - ptype = polys->id & 0x1f; + ptype = polys->id & 31; if (ptype != 11 && ptype != 21 && ptype != 23) { @@ -825,23 +830,21 @@ void PlotBuildingModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) gte_nclip(); gte_stopz(&opz); - r = rot; - if (ptype == 21) { pc->colour = combo & 0x2ffffffU | 0x2c000000; } else { - pc->colour = pc->f4colourTable[(r >> 3) * 4 - polys->th & 31]; + pc->colour = pc->f4colourTable[r - polys->th & 31]; } if (opz > 0) { gte_stsz3(&pc->scribble[0], &pc->scribble[1], &pc->scribble[2]); - pc->tpage = (*pc->ptexture_pages)[polys->texture_set] << 0x10; - pc->clut = (*pc->ptexture_cluts)[polys->texture_set][polys->texture_id] << 0x10; + pc->tpage = (*pc->ptexture_pages)[polys->texture_set]; + pc->clut = (*pc->ptexture_cluts)[polys->texture_set][polys->texture_id]; minZ = pc->scribble[2]; if (pc->scribble[1] < minZ) @@ -896,8 +899,8 @@ void PlotBuildingModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) gte_stsxy(&prims->x3); - prims->tpage = pc->tpage >> 0x10; - prims->clut = pc->clut >> 0x10; + prims->tpage = pc->tpage; + prims->clut = pc->clut; *(ushort*)&prims->u0 = uv0; *(ushort*)&prims->u1 = uv1; @@ -910,13 +913,14 @@ void PlotBuildingModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) } else { - r = n; + int sub; + sub = n; if (n == 1) { if (minZ - 150 < (diff << 1)) - r = 4; + sub = 4; else - r = 2; + sub = 2; } copyVector(&subdiVerts.verts[0][0], &srcVerts[polys->v0]); @@ -931,8 +935,8 @@ void PlotBuildingModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) copyVector(&subdiVerts.verts[0][3], &srcVerts[polys->v2]); subdiVerts.verts[0][3].uv.val = uv2; - makeMesh((MVERTEX(*)[5][5])subdiVerts.verts, r, r); - drawMesh((MVERTEX(*)[5][5])subdiVerts.verts, r, r, pc); + makeMesh((MVERTEX(*)[5][5])subdiVerts.verts, sub, sub); + drawMesh((MVERTEX(*)[5][5])subdiVerts.verts, sub, sub, pc); } } @@ -955,10 +959,10 @@ int DrawAllBuildings(CELL_OBJECT** objects, int num_buildings) for (i = 0; i < 8; i++) { - plotContext.f4colourTable[i * 4 + 0] = planeColours[i] | 0x2C000000; - plotContext.f4colourTable[i * 4 + 1] = planeColours[0] | 0x2C000000; - plotContext.f4colourTable[i * 4 + 2] = planeColours[5] | 0x2C000000; - plotContext.f4colourTable[i * 4 + 3] = planeColours[0] | 0x2C000000; // default: 0x2C00F0F0 + plotContext.f4colourTable[i * 4 + 0] = plotContext.planeColours[i] | 0x2C000000; + plotContext.f4colourTable[i * 4 + 1] = plotContext.planeColours[0] | 0x2C000000; + plotContext.f4colourTable[i * 4 + 2] = plotContext.planeColours[5] | 0x2C000000; + plotContext.f4colourTable[i * 4 + 3] = plotContext.planeColours[0] | 0x2C000000; // default: 0x2C00F0F0 } plotContext.current = current; @@ -1015,13 +1019,10 @@ int DrawAllBuildings(CELL_OBJECT** objects, int num_buildings) // [D] [T] [A] custom void PlotModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) { - int opz; + int opz, Z, r, pr, nr; int diff, minZ, maxZ; - int Z; PL_POLYFT4* polys; int i; - int r; - u_char temp; u_char ptype; POLY_FT4* prims; SVECTOR* srcVerts; @@ -1033,11 +1034,16 @@ void PlotModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) MVERTEX5x5 subdiVerts; #endif + ConvertPolygonTypes(model, pc); + srcVerts = (SVECTOR*)model->vertices; polys = (PL_POLYFT4*)model->poly_block; combo = combointensity; + pr = (rot >> 3) * 4; + nr = ((rot + 32 & 63) >> 3) * 4; + // transparent object flag if (pc->flags & PLOT_TRANSPARENT) combo |= 0x2000000; @@ -1047,19 +1053,7 @@ void PlotModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) { // iterate through polygons // with skipping - ptype = polys->id & 0x1f; - - if ((ptype & 0x1) == 0 && ptype != 8) // is FT3 triangle? - { - temp = polys->uv2.v; - polys->uv3.u = polys->uv2.u; - polys->uv3.v = temp; - - polys->v3 = polys->v2; - - polys->id |= 1; - ptype |= 1; - } + ptype = polys->id & 31; if (ptype != 11 && ptype != 21 && ptype != 23) { @@ -1076,12 +1070,12 @@ void PlotModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) gte_nclip(); gte_stopz(&opz); - r = rot; + r = pr; if (pc->flags & (PLOT_INV_CULL | PLOT_NO_CULL)) { if (opz < 0) - r = rot + 32 & 63; + r = nr; if (pc->flags & PLOT_NO_CULL) opz = 1; // no culling @@ -1095,22 +1089,17 @@ void PlotModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) } else { - temp = polys->th; - - if ((polys->th & 0x80) == 0) // cache normal index if it were not - temp = polys->th = normalIndex(srcVerts, *(u_int*)&polys->v0); - - pc->colour = pc->f4colourTable[(r >> 3) * 4 - temp & 31]; + pc->colour = pc->f4colourTable[r - polys->th & 31]; } if (opz > 0) { gte_stsz3(&pc->scribble[0], &pc->scribble[1], &pc->scribble[2]); - pc->tpage = (*pc->ptexture_pages)[polys->texture_set] << 0x10; + pc->tpage = (*pc->ptexture_pages)[polys->texture_set]; if ((pc->flags & PLOT_CUSTOM_PALETTE) == 0) // [A] custom palette flag - for pedestrian heads - pc->clut = (*pc->ptexture_cluts)[polys->texture_set][polys->texture_id] << 0x10; + pc->clut = (*pc->ptexture_cluts)[polys->texture_set][polys->texture_id]; minZ = pc->scribble[2]; if (pc->scribble[1] < minZ) @@ -1165,8 +1154,8 @@ void PlotModelSubdivNxN(MODEL* model, int rot, _pct* pc, int n) gte_stsxy(&prims->x3); - prims->tpage = pc->tpage >> 0x10; - prims->clut = pc->clut >> 0x10; + prims->tpage = pc->tpage; + prims->clut = pc->clut; *(ushort*)&prims->u0 = uv0; *(ushort*)&prims->u1 = uv1; @@ -1235,10 +1224,10 @@ void RenderModel(MODEL* model, MATRIX* matrix, VECTOR* pos, int zBias, int flags for (i = 0; i < 8; i++) { - plotContext.f4colourTable[i * 4 + 0] = planeColours[i] | 0x2C000000; - plotContext.f4colourTable[i * 4 + 1] = planeColours[0] | 0x2C000000; - plotContext.f4colourTable[i * 4 + 2] = planeColours[5] | 0x2C000000; - plotContext.f4colourTable[i * 4 + 3] = planeColours[0] | 0x2C000000; // default: 0x2C00F0F0 + plotContext.f4colourTable[i * 4 + 0] = plotContext.planeColours[i] | 0x2C000000; + plotContext.f4colourTable[i * 4 + 1] = plotContext.planeColours[0] | 0x2C000000; + plotContext.f4colourTable[i * 4 + 2] = plotContext.planeColours[5] | 0x2C000000; + plotContext.f4colourTable[i * 4 + 3] = plotContext.planeColours[0] | 0x2C000000; // default: 0x2C00F0F0 } plotContext.ptexture_pages = &texture_pages; @@ -1291,20 +1280,19 @@ struct DrawMapData // [D] [T] void DrawMapPSX(int* comp_val) { - int dir; - PACKED_CELL_OBJECT* ppco; - int distScale; - int cellx; - int cellz; CELL_OBJECT* cop; + PACKED_CELL_OBJECT* ppco; MODEL* model; - int hloop; - int vloop; + int dir; + int distScale; + int cellx, cellz; + int hloop, vloop; -#if 0 //def PSX +#ifdef PSX CELL_ITERATOR& ci = *(CELL_ITERATOR*)(u_char*)getScratchAddr(0); MATRIX& mRotStore = *(MATRIX*)((u_char*)getScratchAddr(0) + sizeof(CELL_ITERATOR)); DrawMapData& drawData = *(DrawMapData*)((u_char*)getScratchAddr(0) + sizeof(CELL_ITERATOR) + sizeof(MATRIX)); + static_assert(sizeof(CELL_ITERATOR) + sizeof(MATRIX) + sizeof(DrawMapData) < 1024 - sizeof(_pct), "scratchpad overflow"); #else CELL_ITERATOR ci; MATRIX mRotStore; @@ -1353,7 +1341,7 @@ void DrawMapPSX(int* comp_val) drawData.tiles_found = 0; drawData.sprites_found = 0; - drawData.current_object_computed_value = *comp_val; + drawData.current_object_computed_value = (*comp_val & 4095) | drawData.cellLevel << 16; drawData.other_models_found = 0; drawData.anim_objs_found = 0; @@ -1378,11 +1366,11 @@ void DrawMapPSX(int* comp_val) // walk through all cells do { - if (ABS(hloop) + ABS(vloop) < 21) + if (ABS(hloop) + ABS(vloop) < PVS_CELL_COUNT) { // clamped vis values - int vis_h = MIN(MAX(hloop, -9), 10); - int vis_v = MIN(MAX(vloop, -9), 10); + int vis_h = MIN(MAX(hloop, -9), PVS_CELL_COUNT / 2); + int vis_v = MIN(MAX(vloop, -9), PVS_CELL_COUNT / 2); cellx = drawData.cellxpos + hloop; cellz = drawData.cellzpos + vloop; @@ -1394,10 +1382,8 @@ void DrawMapPSX(int* comp_val) cellz > -1 && cellz < cells_down && PVS_ptr[vis_v * pvs_square + vis_h]) // check PVS table { - ppco = GetFirstPackedCop(cellx, cellz, &ci, 1, drawData.cellLevel); - // walk each cell object in cell - while (ppco != NULL) + for (ppco = GetFirstPackedCop(cellx, cellz, &ci, 1, drawData.cellLevel); ppco; ppco = GetNextPackedCop(&ci)) { model = modelpointers[(ppco->value >> 6) | ((ppco->pos).vy & 1) << 10]; @@ -1435,25 +1421,19 @@ void DrawMapPSX(int* comp_val) } else { - int modelNumber; - modelNumber = ppco->value & 0x3f; - - if (modelNumber > 0) - { - MATRIX2* cmat; - cmat = &CompoundMatrix[modelNumber]; + int yang; + MATRIX2* cmat; - if (cmat->computed != drawData.current_object_computed_value) - { - cmat->computed = drawData.current_object_computed_value; - - gte_ReadRotMatrix(&mRotStore); - gte_sttr(mRotStore.t); + yang = ppco->value & 63; + cmat = &CompoundMatrix[yang]; - MulMatrix0(&inv_camera_matrix, (MATRIX*)&matrixtable[modelNumber], (MATRIX*)cmat); - - gte_SetRotMatrix(&mRotStore); - } + if (cmat->computed != drawData.current_object_computed_value) + { + cmat->computed = drawData.current_object_computed_value; + if (yang > 0) + MulMatrix0(&inv_camera_matrix, (MATRIX*)&matrixtable[yang], (MATRIX*)cmat); + else + *(MATRIX*)cmat = inv_camera_matrix; } if ((model->shape_flags & (SHAPE_FLAG_WATER | SHAPE_FLAG_TILE)) || @@ -1486,13 +1466,11 @@ void DrawMapPSX(int* comp_val) if (drawData.other_models_found < MAX_DRAWN_BUILDINGS) model_object_ptrs[drawData.other_models_found++] = cop; - if ((model->flags2 & MODEL_FLAG_ANIMOBJ) && drawData.anim_objs_found < MAX_DRAWN_ANIMATING) + if (drawData.anim_objs_found < MAX_DRAWN_ANIMATING && (model->flags2 & MODEL_FLAG_ANIMOBJ)) anim_obj_buffer[drawData.anim_objs_found++] = cop; } } } - - ppco = GetNextPackedCop(&ci); } } } @@ -1534,24 +1512,27 @@ void DrawMapPSX(int* comp_val) SetTextColour(255, 255, 0); - sprintf(tempBuf, "Buildings: %d", other_models_found); + sprintf(tempBuf, "Buildings: %d", drawData.other_models_found); PrintString(tempBuf, 10, 60); - sprintf(tempBuf, "Sprites: %d", sprites_found); + sprintf(tempBuf, "Sprites: %d", drawData.sprites_found); PrintString(tempBuf, 10, 75); - sprintf(tempBuf, "Tiles: %d", tiles_found); + sprintf(tempBuf, "Tiles: %d", drawData.tiles_found); PrintString(tempBuf, 10, 90); - sprintf(tempBuf, "Anims: %d", anim_objs_found); + sprintf(tempBuf, "Anims: %d", drawData.anim_objs_found); PrintString(tempBuf, 10, 105); - sprintf(tempBuf, "TOTAL: %d", other_models_found + sprites_found + tiles_found + anim_objs_found); + sprintf(tempBuf, "TOTAL: %d", drawData.other_models_found + drawData.sprites_found + drawData.tiles_found + drawData.anim_objs_found); PrintString(tempBuf, 10, 120); #endif SetupPlaneColours(combointensity); + if (drawData.anim_objs_found) + DrawAllAnimatingObjects((CELL_OBJECT**)anim_obj_buffer, drawData.anim_objs_found); + if (drawData.sprites_found) DrawSprites((PACKED_CELL_OBJECT**)spriteList, drawData.sprites_found); @@ -1561,8 +1542,74 @@ void DrawMapPSX(int* comp_val) if (drawData.other_models_found) DrawAllBuildings((CELL_OBJECT**)model_object_ptrs, drawData.other_models_found); - if (drawData.anim_objs_found) - DrawAllAnimatingObjects((CELL_OBJECT**)anim_obj_buffer, drawData.anim_objs_found); - setupYet = 0; } + +#ifdef DYNAMIC_LIGHTING +struct DLIGHT +{ + SVECTOR position; + CVECTOR color; +}; + +int gEnableDlights = 0; + +int gNumDlights = 0; +DLIGHT gLights[MAX_DLIGHTS]; + +void AddDlight(VECTOR* position, CVECTOR* color, int radius) +{ + DLIGHT* pLight; + VECTOR lightPos; + if (gNumDlights + 1 >= MAX_DLIGHTS) + { + return; + } + + pLight = &gLights[gNumDlights++]; + + lightPos = *position; + VecCopy(&pLight->position, &lightPos); + pLight->position.pad = ABS(radius); + + pLight->color = *color; +} + +void GetDLightLevel(SVECTOR* position, u_int* inOutColor) +{ + DLIGHT* pLight; + int dx, dy, dz, dist, light; + u_int lightR, lightG, lightB; + + lightR = (*inOutColor & 255); + lightG = (*inOutColor >> 8 & 255); + lightB = (*inOutColor >> 16 & 255); + + for (int i = 0; i < gNumDlights; i++) + { + int radius; + pLight = &gLights[i]; + + dx = (int)position->vx - (int)pLight->position.vx; + dy = (int)position->vy - (int)pLight->position.vy; + dz = (int)position->vz - (int)pLight->position.vz; + + dist = SquareRoot0(dx * dx + dy * dy + dz * dz); + + radius = pLight->position.pad; + + if (dist > radius) { + continue; + } + + light = radius - dist; + + lightR += pLight->color.r * light >> 13; + lightG += pLight->color.g * light >> 13; + lightB += pLight->color.b * light >> 13; + } + + *inOutColor = MIN(lightB, 255) << 16 | MIN(lightG, 255) << 8 | MIN(lightR, 255) | (*inOutColor & 0xFF000000); +} + +#endif // DYNAMIC_LIGHTING \ No newline at end of file diff --git a/src_rebuild/Game/C/draw.h b/src_rebuild/Game/C/draw.h index 26477a77c..862974f69 100644 --- a/src_rebuild/Game/C/draw.h +++ b/src_rebuild/Game/C/draw.h @@ -1,26 +1,42 @@ #ifndef DRAW_H #define DRAW_H +enum PlotFlags +{ + PLOT_TRANSPARENT = (1 << 0), + PLOT_INV_CULL = (1 << 1), + PLOT_NO_CULL = (1 << 2), + PLOT_NO_SHADE = (1 << 3), + PLOT_CUSTOM_PALETTE = (1 << 4), +}; + // Primitive plot context used in scratchpad struct _pct { - struct DB* current; + int f4colourTable[32]; + u_int planeColours[8]; + int scribble[8]; u_short(*ptexture_pages)[128]; u_short(*ptexture_cluts)[128][32]; - int f4colourTable[32]; + struct DB* current; + SVECTOR* verts; int* polySizes; char* primptr; OTTYPE* ot; - u_int clut; - u_int tpage; u_int colour; - int flags; - SVECTOR* verts; - u_int lastTexInfo; - int scribble[8]; - int model; + u_int flags; + u_short clut; + u_short tpage; }; +#ifdef DYNAMIC_LIGHTING +extern int gEnableDlights; +extern int gNumDlights; + +extern void AddDlight(VECTOR* position, CVECTOR* color, int radius); +extern void GetDLightLevel(SVECTOR* position, u_int* inOutColor); +#endif + extern SVECTOR day_vectors[4]; extern SVECTOR night_vectors[4]; extern SVECTOR day_colours[4]; @@ -60,15 +76,6 @@ extern _pct& plotContext; #endif -enum PlotFlags -{ - PLOT_TRANSPARENT = (1 << 0), - PLOT_INV_CULL = (1 << 1), - PLOT_NO_CULL = (1 << 2), - PLOT_NO_SHADE = (1 << 3), - PLOT_CUSTOM_PALETTE = (1 << 4), -}; - extern void* model_tile_ptrs[MAX_DRAWN_TILES]; extern int units_across_halved; @@ -84,7 +91,7 @@ extern int combointensity; extern int gForceLowDetailCars; extern int num_cars_drawn; -extern char CurrentPVS[444]; +extern int PositionVisible(VECTOR* pos); // 0x0005D560 extern void DrawMapPSX(int *comp_val); // 0x0003F6B0 diff --git a/src_rebuild/Game/C/drivinggames.c b/src_rebuild/Game/C/drivinggames.c index 15d7c7d03..821206391 100644 --- a/src_rebuild/Game/C/drivinggames.c +++ b/src_rebuild/Game/C/drivinggames.c @@ -27,11 +27,12 @@ struct TRAILBLAZER_DATA struct SMASHED_CONE { + VECTOR position; + VECTOR velocity; + short rot_speed; char cone; u_char active : 7; u_char side : 1; - short rot_speed; - VECTOR velocity; }; MODEL* gTrailblazerConeModel; @@ -67,7 +68,7 @@ void InitDrivingGames(void) if(NewLevel) { - gTrailblazerData = (TRAILBLAZER_DATA*)D_MALLOC(1200); // [A] use malloc + gTrailblazerData = (TRAILBLAZER_DATA*)D_MALLOC(sizeof(TRAILBLAZER_DATA) * 100); // [A] use malloc sprintf(filename, "TRAILS\\TRAIL.%d", gCurrentMissionNumber); @@ -125,7 +126,7 @@ int CarConeCollision(VECTOR *pPos, int car) return bcollided2d(cd); } - +void GetConePos(int cone, VECTOR* pos, int side); // [D] [T] void SetSmashedCone(int cone, VECTOR *velocity, int player, int side) @@ -144,6 +145,8 @@ void SetSmashedCone(int cone, VECTOR *velocity, int player, int side) sc->side = side; sc->cone = cone; + GetConePos(cone, &sc->position, side); + sc->velocity.vx = velocity->vx >> 10; sc->velocity.vz = velocity->vz >> 10; @@ -198,11 +201,11 @@ void MoveSmashedCones(void) { tbd = &gTrailblazerData[sc->cone]; - if (tbd->y < 50 - player[0].pos[1]) + if (sc->position.vy < 50 - player[0].pos[1]) { - tbd->x += sc->velocity.vx; - tbd->y += sc->velocity.vy; - tbd->z += sc->velocity.vz; + sc->position.vx += sc->velocity.vx; + sc->position.vy += sc->velocity.vy; + sc->position.vz += sc->velocity.vz; sc->velocity.vy += 10; sc->active++; @@ -245,19 +248,22 @@ void DrawCone(VECTOR *position, int cone) } // [D] [T] -void DrawSmashedCone(SMASHED_CONE *sc, VECTOR *wpos) +void DrawSmashedCone(SMASHED_CONE *sc) { MATRIX object_matrix; VECTOR pos; + if (FrustrumCheck(&sc->position, gTrailblazerConeModel->bounding_sphere) == -1) + return; + InitMatrix(object_matrix); - RotMatrixY(sc->rot_speed * sc->active * 3 & 0xfff, &object_matrix); - RotMatrixZ(sc->rot_speed * sc->active & 0xfff, &object_matrix); + RotMatrixY(sc->rot_speed * sc->active * 3 & 4095, &object_matrix); + RotMatrixZ(sc->rot_speed * sc->active & 4095, &object_matrix); - pos.vx = wpos->vx - camera_position.vx; - pos.vy = wpos->vy - camera_position.vy; - pos.vz = wpos->vz - camera_position.vz; + pos.vx = sc->position.vx - camera_position.vx; + pos.vy = sc->position.vy - camera_position.vy; + pos.vz = sc->position.vz - camera_position.vz; Apply_Inv_CameraMatrix(&pos); SetRotMatrix(&object_matrix); @@ -265,11 +271,7 @@ void DrawSmashedCone(SMASHED_CONE *sc, VECTOR *wpos) gte_SetTransVector(&pos); SetFrustrumMatrix(); - - if (FrustrumCheck(wpos, gTrailblazerConeModel->bounding_sphere) != -1) - { - PlotMDL_less_than_128(gTrailblazerConeModel); - } + PlotMDL_less_than_128(gTrailblazerConeModel); } // [D] [T] @@ -331,13 +333,11 @@ void DrawSmashedCones(void) { if (GameType == GAME_GATERACE) { - GetConePos(sc->cone, &wpos, sc->side); - DrawSmashedCone(sc, &wpos); + DrawSmashedCone(sc); } else { - GetConePos(sc->cone, &wpos, -1); - DrawSmashedCone(sc, &wpos); + DrawSmashedCone(sc); } } } @@ -477,7 +477,7 @@ void HandleDrivingGames(void) vel.vy = -17; vel.vz = FIXED(car_data[playerCarId].st.n.linearVelocity[2]); - SetSmashedCone(cone, &vel, id, 0); + SetSmashedCone(cone, &vel, id, -1); gTrailblazerConeCount++; gTrailblazerConeIndex += i + 1; diff --git a/src_rebuild/Game/C/event.c b/src_rebuild/Game/C/event.c index 64da3c7c3..bf1298dcf 100644 --- a/src_rebuild/Game/C/event.c +++ b/src_rebuild/Game/C/event.c @@ -556,6 +556,12 @@ static EventCamera eventCamera; void MakeEventTrackable(EVENT* ev); +#ifdef PSX +#define EVENT_DRAW_DISTANCE VIEW_DRAW_DISTANCE +#else +#define EVENT_DRAW_DISTANCE 15000 // [A] world becomes repetetive if further :( +#endif // PSX + // [D] [T] int GetVisValue(int index, int zDir) { @@ -566,17 +572,16 @@ int GetVisValue(int index, int zDir) if (index & 0xC000) { - camera = (index >> 0xf ^ 1) & 1; + camera = (index >> 15 ^ 1) & 1; + radius = EVENT_DRAW_DISTANCE; if (zDir == 0) { pos.vx = player[camera].cameraPos.vx; - radius = 16000; } else { pos.vx = player[camera].cameraPos.vz; - radius = 16000; } } else @@ -584,9 +589,9 @@ int GetVisValue(int index, int zDir) int multiple; if (index & 0x80) - ev = (EVENT*)&fixedEvent[index & 0x7f]; + ev = (EVENT*)&fixedEvent[index & 127]; else - ev = &event[index & 0x7f]; + ev = &event[index & 127]; if (index & 0xf00) { @@ -748,9 +753,9 @@ void VisibilityLists(VisType type, int i) else if (type == VIS_ADD) { if (i & 0x80) - ev = (EVENT*)&fixedEvent[i & 0x7f]; + ev = (EVENT*)&fixedEvent[i & 127]; else - ev = &event[i & 0x7f]; + ev = &event[i & 127]; if (ev->radius == 0) { @@ -1087,7 +1092,7 @@ void SetUpEvents(int full) missionTrain[1].engine = missionTrain[0].engine; // add trains - while (n < count-1) + while (n < count) { // randomize carriage count if (n != 0) @@ -1741,7 +1746,7 @@ void StepFromToEvent(EVENT* ev) { int df; int md; - long* curr; + decltype(VECTOR::vx)* curr; int* to; int direction; int d, d2; @@ -1833,7 +1838,7 @@ void StepPathEvent(EVENT* ev) int* to; Station station; int direction; - long* curr; + decltype(VECTOR::vx)* curr; int dir; int turn[4]; XZPAIR centre; @@ -2038,7 +2043,7 @@ void StepPathEvent(EVENT* ev) ev->position.vx += offset.x; ev->position.vz += offset.z; - ev->rotation = ratan2(offset.x, offset.z) + 1024U & 0xfff; + ev->rotation = ratan2(offset.x, offset.z) + 1024U & 4095; if (ev->flags & 0x8000) { @@ -2330,7 +2335,7 @@ void StepHelicopter(EVENT* ev) } ev->rotation += FIXEDH(FIXEDH(direction * direction) * direction); - ev->rotation &= 0xfff; + ev->rotation &= 4095; if (GetSurfaceIndex(&ev->position) == -23) { @@ -2603,7 +2608,7 @@ void StepEvents(void) } chicagoDoor[2].rotation -= chicagoDoor[2].active; - chicagoDoor[2].rotation &= 0xfff; + chicagoDoor[2].rotation &= 4095; } } @@ -2643,9 +2648,9 @@ void StepEvents(void) if ((*x & otherCamera) == 0) { if ((*x & 0x80) == 0) - evt = &event[*x & 0x7f]; + evt = &event[*x & 127]; else - evt = (EVENT*)&fixedEvent[*x & 0x7f]; + evt = (EVENT*)&fixedEvent[*x & 127]; // events that enable drawing if ((evt->flags & 0x204) == 0x200) @@ -2654,7 +2659,7 @@ void StepEvents(void) while ((*z & thisCamera) == 0) { - if ((*z & otherCamera) == 0 && (*x & 0xfff) == (*z & 0xfff)) + if ((*z & otherCamera) == 0 && (*x & 4095) == (*z & 4095)) { cop = &EventCop[event_models_active++]; @@ -2777,7 +2782,7 @@ void DrawRotor(VECTOR pos, MATRIX* matrix) pos.vy -= camera_position.vy; pos.vz -= camera_position.vz; - _RotMatrixY(&localMat, HelicopterData.rotorrot & 0xfff); + _RotMatrixY(&localMat, HelicopterData.rotorrot & 4095); ApplyMatrixSV(matrix, v, v); MulMatrix0(matrix, &localMat, &localMat); ApplyMatrixSV(&localMat, v + 1, v + 1); @@ -2925,15 +2930,15 @@ void DrawEvents(int camera) if ((*x & otherCamera) == 0) { if ((*x & 0x80) == 0) - ev = &event[*x & 0x7f]; + ev = &event[*x & 127]; else - ev = (EVENT*)&fixedEvent[*x & 0x7f]; + ev = (EVENT*)&fixedEvent[*x & 127]; z = zVis; while ((*z & thisCamera) == 0) { - if ((*z & otherCamera) == 0 && (*x & 0xfff) == (*z & 0xfff)) + if ((*z & otherCamera) == 0 && (*x & 4095) == (*z & 4095)) { if ((ev->flags & 4) == 0 && (ev->flags & 1) == camera) { @@ -3051,9 +3056,9 @@ void DrawEvents(int camera) { if (ev->model == HelicopterData.cleanModel) { - _RotMatrixZ(&matrix, HelicopterData.roll & 0xfff); - _RotMatrixX(&matrix, HelicopterData.pitch & 0xfff); - _RotMatrixY(&matrix, ev->rotation & 0xfff); + _RotMatrixZ(&matrix, HelicopterData.roll & 4095); + _RotMatrixX(&matrix, HelicopterData.pitch & 4095); + _RotMatrixY(&matrix, ev->rotation & 4095); DrawRotor(ev->position, &matrix); @@ -3132,7 +3137,7 @@ void DrawEvents(int camera) pos.vy += ev->data[2]; - if (gTimeOfDay != 1) + if (gTimeOfDay != TIME_DAY) SetupPlaneColours(0x00282828); RenderModel(foam.model, &matrix, &pos, 200, (foam.rotate & 0x8000) ? 0x3 : 0x1, 1, 0); @@ -3144,6 +3149,7 @@ void DrawEvents(int camera) { SetCamera(ev); DrawMapPSX(&ObjectDrawnValue); + ObjectDrawnValue += 16; } } } @@ -4022,7 +4028,7 @@ void MultiCarEvent(MS_TARGET* target) ev->position.vx = mcd->x; ev->position.vz = mcd->z; - ev->position.vy = -312; + ev->position.vy = -312; // MapHeight may not be available due to region is not yet loaded ev->rotation = mcd->rot; diff --git a/src_rebuild/Game/C/felony.c b/src_rebuild/Game/C/felony.c index abfb7a228..13c388408 100644 --- a/src_rebuild/Game/C/felony.c +++ b/src_rebuild/Game/C/felony.c @@ -386,7 +386,7 @@ void CheckPlayerMiscFelonies(void) NoteFelony(&felonyData, 8, 4096); // if lights are off (broken) - if (gTimeOfDay == 3 && cp->ap.damage[0] > 1000 && cp->ap.damage[1] > 1000) + if (gTimeOfDay == TIME_NIGHT && cp->ap.damage[0] > 1000 && cp->ap.damage[1] > 1000) NoteFelony(&felonyData, 9, 4096); // reckless driving. diff --git a/src_rebuild/Game/C/gamesnd.c b/src_rebuild/Game/C/gamesnd.c index 1ed5e8a08..5d780eb1e 100644 --- a/src_rebuild/Game/C/gamesnd.c +++ b/src_rebuild/Game/C/gamesnd.c @@ -206,15 +206,17 @@ int ResidentModelsBodge(void) int i; int j; - j = MissionHeader->residentModels[4]; - - if (gCurrentMissionNumber == 24 || gCurrentMissionNumber == 27 || + if (gCurrentMissionNumber == 24 || + gCurrentMissionNumber == 27 || gCurrentMissionNumber == 29 || - (gCurrentMissionNumber == 30 || gCurrentMissionNumber == 35)) + gCurrentMissionNumber == 30 || + gCurrentMissionNumber == 35) { return 3; } + j = MissionHeader->residentModels[4]; + if (gCurrentMissionNumber - 50U < 16 && j == 12) { return 5; @@ -224,7 +226,7 @@ int ResidentModelsBodge(void) { i = 11; - if (j != 9) + if (j != 9 && j != i) return 3; } else if (GameLevel == 1) @@ -271,7 +273,6 @@ int MapCarIndexToBank(int index) model = RM[index]; - // [A] Rev 1.1 removes this block if (gCurrentMissionNumber - 39U < 2 && RM[index] == 13) { model = 10 - (RM[0] + RM[1] + RM[2]); @@ -304,7 +305,7 @@ void LoadLevelSFX(int missionNum) int i; u_int city_night_fx; - city_night_fx = (gTimeOfDay == 3); + city_night_fx = (gTimeOfDay == TIME_NIGHT); cop_bank = missionNum % 4 + 1; cop_model = 3; @@ -1005,20 +1006,19 @@ void DoDopplerSFX(void) } } - // sort cars by distance distance - for (i = 0; i < num_noisy_cars - 1; i++) + // sort cars by distance + for (i = 1; i < num_noisy_cars; i++) { - for (j = i + 1; j < num_noisy_cars; j++) - { - int tmpi; - tmpi = indexlist[i]; + int tmpi; + tmpi = indexlist[i]; - if (car_dist[indexlist[j]] < car_dist[tmpi]) - { - indexlist[i] = indexlist[j]; - indexlist[j] = tmpi; - } + j = i - 1; + while (j >= 0 && car_dist[indexlist[j]] > car_dist[tmpi]) + { + indexlist[j + 1] = indexlist[j]; + j = j - 1; } + indexlist[j + 1] = tmpi; } car_flags = 0; @@ -1244,6 +1244,7 @@ void DoDopplerSFX(void) // update sounds of cars (swap between idle and rev) for (j = 0; j < MAX_CAR_NOISES; j++) { + CAR_DATA* cp; char old_idle; if (car_noise[j].in_use == 0) @@ -1251,12 +1252,13 @@ void DoDopplerSFX(void) car = car_noise[j].car; old_idle = car_noise[j].idle; + cp = &car_data[car]; // determine which sound type it has to play if (gInGameCutsceneActive != 0 && force_idle[car] > -1) car_noise[j].idle = force_idle[car]; else - car_noise[j].idle = (car_data[car].hd.speed < 17); + car_noise[j].idle = (cp->hd.speed < 17); // restart sound if it's changed if (old_idle != car_noise[j].idle) @@ -1266,7 +1268,7 @@ void DoDopplerSFX(void) StopChannel(car_noise[j].chan); UnlockChannel(car_noise[j].chan); - model = car_data[car].ap.model; + model = cp->ap.model; if (model == 3) model = cop_model; @@ -1284,9 +1286,7 @@ void DoDopplerSFX(void) else sample = bank * 3; - car_noise[j].chan = Start3DTrackingSound(-1, SOUND_BANK_CARS, sample, - (VECTOR*)car_data[car].hd.where.t, - (LONGVECTOR3*)car_data[car].st.n.linearVelocity); + car_noise[j].chan = Start3DTrackingSound(-1, SOUND_BANK_CARS, sample, (VECTOR*)cp->hd.where.t, (LONGVECTOR3*)cp->st.n.linearVelocity); LockChannel(car_noise[j].chan); } @@ -1305,10 +1305,7 @@ void DoDopplerSFX(void) car_noise[j].in_use = 1; - SetChannelPosition3(car_noise[j].chan, - (VECTOR*)car_data[car].hd.where.t, - (LONGVECTOR3*)car_data[car].st.n.linearVelocity, - volume, pitch, 0); + SetChannelPosition3(car_noise[j].chan, (VECTOR*)cp->hd.where.t, (LONGVECTOR3*)cp->st.n.linearVelocity, volume, pitch, 0); } // bark on player @@ -1324,13 +1321,12 @@ void DoDopplerSFX(void) } // update each sound channel with new info - for (j = 0; j < MAX_SFX_CHANNELS; j++) + CHANNEL_DATA* c = &channels[0]; + for (j = 0; j < MAX_SFX_CHANNELS; j++, c++) { - if (channels[j].loop == 0 && channels[j].time != 0 && channels[j].srcposition != NULL) + if ((c->flags & CHAN_LOOP) == 0 && c->time != 0 && c->srcposition != NULL) { - SetChannelPosition3(j, - channels[j].srcposition, channels[j].srcvelocity, - channels[j].srcvolume, channels[j].srcpitch, 0); + SetChannelPosition3(j, c->srcposition, c->srcvelocity, c->srcvolume, c->srcpitch, 0); } } } @@ -1583,7 +1579,7 @@ void FunkUpDaBGMTunez(int funk) if (copmusic != 0) { copmusic = 0; - XM_SetSongPos(Song_ID, 0); + Song_SetPos = 0; } } else @@ -1591,7 +1587,7 @@ void FunkUpDaBGMTunez(int funk) if (copmusic == 0) { copmusic = 1; - XM_SetSongPos(Song_ID, xm_coptrackpos[current_music_id]); + Song_SetPos = xm_coptrackpos[current_music_id]; } } } diff --git a/src_rebuild/Game/C/glaunch.c b/src_rebuild/Game/C/glaunch.c index 15f268f09..f4dd417af 100644 --- a/src_rebuild/Game/C/glaunch.c +++ b/src_rebuild/Game/C/glaunch.c @@ -26,76 +26,81 @@ struct MISSION_STEP u_char disc : 1; }; -MISSION_STEP MissionLadder[68] = +#define DML_FMV 1 +#define DML_MISSION 2 +#define DML_CREDITS 4 +#define DML_RECAP 6 + +MISSION_STEP MissionLadder[] = { - { 1, 0, 1, 0 }, - { 1, 0, 2, 0 }, - { 2, 0, 1, 0 }, - { 2, 1, 2, 0 }, - { 2, 1, 3, 0 }, - { 1, 1, 3, 0 }, - { 1, 1, 4, 0 }, - { 2, 1, 4, 0 }, - { 1, 2, 5, 0 }, - { 2, 2, 5, 0 }, - { 1, 3, 6, 0 }, - { 2, 3, 6, 0 }, - { 1, 4, 7, 0 }, - { 2, 5, 7, 0 }, - { 6, 5, 0, 0 }, - { 2, 5, 9, 0 }, - { 1, 5, 8, 0 }, - { 1, 5, 9, 0 }, - { 2, 6, 10, 0 }, - { 1, 6, 10, 0 }, - { 1, 6, 11, 0 }, - { 2, 7, 11, 0 }, - { 6, 7, 0, 0 }, - { 2, 7, 13, 0 }, - { 2, 7, 14, 0 }, - { 1, 7, 12, 0 }, - { 2, 8, 15, 0 }, - { 2, 8, 16, 0 }, - { 1, 8, 13, 0 }, - { 2, 9, 17, 0 }, - { 2, 9, 18, 0 }, - { 1, 9, 14, 0 }, - { 2, 10, 19, 0 }, - { 1, 10, 15, 0 }, - { 2, 11, 20, 0 }, - { 1, 12, 16, 1 }, - { 1, 12, 17, 1 }, - { 2, 13, 21, 1 }, - { 2, 13, 22, 1 }, - { 2, 13, 23, 1 }, - { 2, 13, 24, 1 }, - { 1, 13, 18, 1 }, - { 2, 14, 25, 1 }, - { 2, 14, 26, 1 }, - { 1, 14, 19, 1 }, - { 2, 15, 27, 1 }, - { 2, 15, 28, 1 }, - { 2, 15, 29, 1 }, - { 2, 15, 30, 1 }, - { 1, 15, 20, 1 }, - { 1, 15, 21, 1 }, - { 2, 16, 31, 1 }, - { 2, 16, 32, 1 }, - { 2, 16, 33, 1 }, - { 2, 16, 34, 1 }, - { 1, 16, 22, 1 }, - { 2, 17, 35, 1 }, - { 6, 17, 0, 1 }, - { 2, 17, 37, 1 }, - { 1, 17, 23, 1 }, - { 2, 18, 38, 1 }, - { 2, 18, 39, 1 }, - { 1, 18, 24, 1 }, - { 2, 19, 40, 1 }, - { 1, 19, 25, 1 }, - { 1, 19, 26, 1 }, - { 1, 19, 27, 1 }, - { 4, 19, 28, 1 } + { DML_FMV, 0, 1, 0 }, + { DML_FMV, 0, 2, 0 }, + { DML_MISSION, 0, 1, 0 }, + { DML_MISSION, 1, 2, 0 }, + { DML_MISSION, 1, 3, 0 }, + { DML_FMV, 1, 3, 0 }, + { DML_FMV, 1, 4, 0 }, + { DML_MISSION, 1, 4, 0 }, + { DML_FMV, 2, 5, 0 }, + { DML_MISSION, 2, 5, 0 }, + { DML_FMV, 3, 6, 0 }, + { DML_MISSION, 3, 6, 0 }, + { DML_FMV, 4, 7, 0 }, + { DML_MISSION, 5, 7, 0 }, + { DML_RECAP, 5, 0, 0 }, + { DML_MISSION, 5, 9, 0 }, + { DML_FMV, 5, 8, 0 }, + { DML_FMV, 5, 9, 0 }, + { DML_MISSION, 6, 10, 0 }, + { DML_FMV, 6, 10, 0 }, + { DML_FMV, 6, 11, 0 }, + { DML_MISSION, 7, 11, 0 }, + { DML_RECAP, 7, 0, 0 }, + { DML_MISSION, 7, 13, 0 }, + { DML_MISSION, 7, 14, 0 }, + { DML_FMV, 7, 12, 0 }, + { DML_MISSION, 8, 15, 0 }, + { DML_MISSION, 8, 16, 0 }, + { DML_FMV, 8, 13, 0 }, + { DML_MISSION, 9, 17, 0 }, + { DML_MISSION, 9, 18, 0 }, + { DML_FMV, 9, 14, 0 }, + { DML_MISSION, 10, 19, 0 }, + { DML_FMV, 10, 15, 0 }, + { DML_MISSION, 11, 20, 0 }, + { DML_FMV, 12, 16, 1 }, + { DML_FMV, 12, 17, 1 }, + { DML_MISSION, 13, 21, 1 }, + { DML_MISSION, 13, 22, 1 }, + { DML_MISSION, 13, 23, 1 }, + { DML_MISSION, 13, 24, 1 }, + { DML_FMV, 13, 18, 1 }, + { DML_MISSION, 14, 25, 1 }, + { DML_MISSION, 14, 26, 1 }, + { DML_FMV, 14, 19, 1 }, + { DML_MISSION, 15, 27, 1 }, + { DML_MISSION, 15, 28, 1 }, + { DML_MISSION, 15, 29, 1 }, + { DML_MISSION, 15, 30, 1 }, + { DML_FMV, 15, 20, 1 }, + { DML_FMV, 15, 21, 1 }, + { DML_MISSION, 16, 31, 1 }, + { DML_MISSION, 16, 32, 1 }, + { DML_MISSION, 16, 33, 1 }, + { DML_MISSION, 16, 34, 1 }, + { DML_FMV, 16, 22, 1 }, + { DML_MISSION, 17, 35, 1 }, + { DML_RECAP, 17, 0, 1 }, + { DML_MISSION, 17, 37, 1 }, + { DML_FMV, 17, 23, 1 }, + { DML_MISSION, 18, 38, 1 }, + { DML_MISSION, 18, 39, 1 }, + { DML_FMV, 18, 24, 1 }, + { DML_MISSION, 19, 40, 1 }, + { DML_FMV, 19, 25, 1 }, + { DML_FMV, 19, 26, 1 }, + { DML_FMV, 19, 27, 1 }, + { DML_CREDITS, 19, 28, 1 } }; unsigned short RecapFrameLength[19] = { @@ -403,7 +408,7 @@ void State_MissionLadder(void* param) SetPleaseWait(NULL); } - if (CurrentStep->flags == 2) + if (CurrentStep->flags == DML_MISSION) { if (RenderArgs.nRenders != 0) { @@ -419,14 +424,14 @@ void State_MissionLadder(void* param) quit = 1; } - else if (CurrentStep->flags == 1) // any render + else if (CurrentStep->flags == DML_FMV) // any render { RenderArgs.Args[RenderArgs.nRenders].render = CurrentStep->data; RenderArgs.Args[RenderArgs.nRenders].recap = 0; RenderArgs.Args[RenderArgs.nRenders].credits = 0; RenderArgs.nRenders++; } - else if (CurrentStep->flags == 4) // ending + else if (CurrentStep->flags == DML_CREDITS) // ending { SetPleaseWait(NULL); diff --git a/src_rebuild/Game/C/handling.c b/src_rebuild/Game/C/handling.c index 77959c0dc..538e0a798 100644 --- a/src_rebuild/Game/C/handling.c +++ b/src_rebuild/Game/C/handling.c @@ -23,6 +23,14 @@ #include "shadow.h" #include "players.h" +struct BOUND_BOX +{ + int x0, y0, z0; + int x1, y1, z1; +}; + +BOUND_BOX bbox[MAX_CARS]; + inline void UpdateCarDrawMatrix(CAR_DATA* cp) { cp->hd.drawCarMat.m[0][0] = -cp->hd.where.m[0][0]; @@ -275,37 +283,20 @@ void GlobalTimeStep(void) static RigidBodyState _d1[MAX_CARS]; // offset 0x820 int mayBeCollidingBits; - int howHard; int tmp; - RigidBodyState* thisState_i; - RigidBodyState* thisState_j; - RigidBodyState* thisDelta; - CAR_DATA* cp; - CAR_DATA* c1; - RigidBodyState* st; - RigidBodyState* tp; - RigidBodyState* d0; - RigidBodyState* d1; + RigidBodyState* thisState_i, *thisState_j, * thisDelta; + CAR_DATA* cp, * c1; + RigidBodyState* st, *tp; + RigidBodyState* d0, *d1; LONGVECTOR4 AV; LONGQUATERNION delta_orientation; - LONGVECTOR4 normal; - LONGVECTOR4 collisionpoint; - LONGVECTOR4 lever0; - LONGVECTOR4 lever1; - LONGVECTOR4 torque; - LONGVECTOR4 pointVel0; + LONGVECTOR4 normal, collisionpoint, lever0, lever1, torque, pointVel0; VECTOR velocity; - int depth; - int RKstep; - int subframe; - int j; - int strikeVel; - int i; - int do1; - int do2; - int m1; - int m2; - int strength; + int subframe, RKstep; + int i, j; + int howHard, depth, strikeVel, strength; + int do1, do2; + int m1, m2; int carsDentedThisFrame; short *felony; @@ -369,38 +360,37 @@ void GlobalTimeStep(void) if ((tmp < st->n.angularVelocity[2]) || (tmp = -tmp, st->n.angularVelocity[2] < tmp)) st->n.angularVelocity[2] = tmp; - // without precision - if (!cp->hd.mayBeColliding) + if (cp->hd.mayBeColliding) { - long* orient = st->n.orientation; // LONGQUATERNION + continue; + } - st->n.fposition[0] += st->n.linearVelocity[0] >> 8; - st->n.fposition[1] += st->n.linearVelocity[1] >> 8; - st->n.fposition[2] += st->n.linearVelocity[2] >> 8; + int* orient = st->n.orientation; // LONGQUATERNION - AV[0] = FixHalfRound(st->n.angularVelocity[0], 13); - AV[1] = FixHalfRound(st->n.angularVelocity[1], 13); - AV[2] = FixHalfRound(st->n.angularVelocity[2], 13); + st->n.fposition[0] += st->n.linearVelocity[0] >> 8; + st->n.fposition[1] += st->n.linearVelocity[1] >> 8; + st->n.fposition[2] += st->n.linearVelocity[2] >> 8; - delta_orientation[0] = -orient[1] * AV[2] + orient[2] * AV[1] + orient[3] * AV[0]; - delta_orientation[1] = orient[0] * AV[2] - orient[2] * AV[0] + orient[3] * AV[1]; - delta_orientation[2] = -orient[0] * AV[1] + orient[1] * AV[0] + orient[3] * AV[2]; - delta_orientation[3] = -orient[0] * AV[0] - orient[1] * AV[1] - orient[2] * AV[2]; + AV[0] = FixHalfRound(st->n.angularVelocity[0], 13); + AV[1] = FixHalfRound(st->n.angularVelocity[1], 13); + AV[2] = FixHalfRound(st->n.angularVelocity[2], 13); - orient[0] += FIXEDH(delta_orientation[0]); - orient[1] += FIXEDH(delta_orientation[1]); - orient[2] += FIXEDH(delta_orientation[2]); - orient[3] += FIXEDH(delta_orientation[3]); + delta_orientation[0] = -orient[1] * AV[2] + orient[2] * AV[1] + orient[3] * AV[0]; + delta_orientation[1] = orient[0] * AV[2] - orient[2] * AV[0] + orient[3] * AV[1]; + delta_orientation[2] = -orient[0] * AV[1] + orient[1] * AV[0] + orient[3] * AV[2]; + delta_orientation[3] = -orient[0] * AV[0] - orient[1] * AV[1] - orient[2] * AV[2]; - RebuildCarMatrix(st, cp); - } + orient[0] += FIXEDH(delta_orientation[0]); + orient[1] += FIXEDH(delta_orientation[1]); + orient[2] += FIXEDH(delta_orientation[2]); + orient[3] += FIXEDH(delta_orientation[3]); + + RebuildCarMatrix(st, cp); } // do collision interactions for(subframe = 0; subframe < 4; subframe++) { - RKstep = 0; - for (RKstep = 0; RKstep < 2; RKstep++) { for (i = 0; i < num_active_cars; i++) @@ -416,315 +406,322 @@ void GlobalTimeStep(void) mayBeCollidingBits = cp->hd.mayBeColliding; // if has any collision, process with double precision - if (mayBeCollidingBits) + if (mayBeCollidingBits == 0) + { + continue; + } + + if (RKstep == 0) + { + thisState_i = &cp->st; + thisDelta = _d0; + } + else + { + thisState_i = &_tp[i]; + thisDelta = _d1; + } + + int* orient = thisState_i->n.orientation; // LONGQUATERNION + + thisDelta[i].n.fposition[0] = thisState_i->n.linearVelocity[0] >> 8; + thisDelta[i].n.fposition[1] = thisState_i->n.linearVelocity[1] >> 8; + thisDelta[i].n.fposition[2] = thisState_i->n.linearVelocity[2] >> 8; + + AV[0] = FixHalfRound(thisState_i->n.angularVelocity[0], 13); + AV[1] = FixHalfRound(thisState_i->n.angularVelocity[1], 13); + AV[2] = FixHalfRound(thisState_i->n.angularVelocity[2], 13); + + thisDelta[i].n.orientation[0] = FIXEDH(-orient[1] * AV[2] + orient[2] * AV[1] + orient[3] * AV[0]); + thisDelta[i].n.orientation[1] = FIXEDH(orient[0] * AV[2] - orient[2] * AV[0] + orient[3] * AV[1]); + thisDelta[i].n.orientation[2] = FIXEDH(-orient[0] * AV[1] + orient[1] * AV[0] + orient[3] * AV[2]); + thisDelta[i].n.orientation[3] = FIXEDH(-orient[0] * AV[0] - orient[1] * AV[1] - orient[2] * AV[2]); + + thisDelta[i].n.linearVelocity[0] = 0; + thisDelta[i].n.linearVelocity[1] = 0; + thisDelta[i].n.linearVelocity[2] = 0; + thisDelta[i].n.angularVelocity[0] = 0; + thisDelta[i].n.angularVelocity[1] = 0; + thisDelta[i].n.angularVelocity[2] = 0; + + for (j = 0; j < i; j++) { - if (RKstep == 0) + c1 = active_car_list[j]; + + // [A] optimized run to not use the box checking + // as it has already composed bitfield / pairs + if ((mayBeCollidingBits & (1 << CAR_INDEX(c1))) == 0 || (c1->hd.speed == 0 && cp->hd.speed == 0)) { - thisState_i = &cp->st; - thisDelta = _d0; + continue; } - else + + if (CarCarCollision3(cp, c1, &depth, (VECTOR*)collisionpoint, (VECTOR*)normal) == 0) { - thisState_i = &_tp[i]; - thisDelta = _d1; + continue; } + + if (RKstep > 0) + thisState_j = &_tp[j]; + else + thisState_j = &c1->st; + + int c1InfiniteMass; + int c2InfiniteMass; + + collisionpoint[1] -= 0; + + lever0[0] = collisionpoint[0] - cp->hd.where.t[0]; + lever0[1] = collisionpoint[1] - cp->hd.where.t[1]; + lever0[2] = collisionpoint[2] - cp->hd.where.t[2]; + + lever1[0] = collisionpoint[0] - c1->hd.where.t[0]; + lever1[1] = collisionpoint[1] - c1->hd.where.t[1]; + lever1[2] = collisionpoint[2] - c1->hd.where.t[2]; + + strength = 47 - (lever0[1] + lever1[1]) / 2; + + lever0[1] += strength; + lever1[1] += strength; - long* orient = thisState_i->n.orientation; // LONGQUATERNION + strikeVel = depth * 0xc000; - thisDelta[i].n.fposition[0] = thisState_i->n.linearVelocity[0] >> 8; - thisDelta[i].n.fposition[1] = thisState_i->n.linearVelocity[1] >> 8; - thisDelta[i].n.fposition[2] = thisState_i->n.linearVelocity[2] >> 8; + pointVel0[0] = (FIXEDH(thisState_i->n.angularVelocity[1] * lever0[2] - thisState_i->n.angularVelocity[2] * lever0[1]) + thisState_i->n.linearVelocity[0]) - + (FIXEDH(thisState_j->n.angularVelocity[1] * lever1[2] - thisState_j->n.angularVelocity[2] * lever1[1]) + thisState_j->n.linearVelocity[0]); - AV[0] = FixHalfRound(thisState_i->n.angularVelocity[0], 13); - AV[1] = FixHalfRound(thisState_i->n.angularVelocity[1], 13); - AV[2] = FixHalfRound(thisState_i->n.angularVelocity[2], 13); + pointVel0[1] = (FIXEDH(thisState_i->n.angularVelocity[2] * lever0[0] - thisState_i->n.angularVelocity[0] * lever0[2]) + thisState_i->n.linearVelocity[1]) - + (FIXEDH(thisState_j->n.angularVelocity[2] * lever1[0] - thisState_j->n.angularVelocity[0] * lever1[2]) + thisState_j->n.linearVelocity[1]); - thisDelta[i].n.orientation[0] = FIXEDH(-orient[1] * AV[2] + orient[2] * AV[1] + orient[3] * AV[0]); - thisDelta[i].n.orientation[1] = FIXEDH(orient[0] * AV[2] - orient[2] * AV[0] + orient[3] * AV[1]); - thisDelta[i].n.orientation[2] = FIXEDH(-orient[0] * AV[1] + orient[1] * AV[0] + orient[3] * AV[2]); - thisDelta[i].n.orientation[3] = FIXEDH(-orient[0] * AV[0] - orient[1] * AV[1] - orient[2] * AV[2]); + pointVel0[2] = (FIXEDH(thisState_i->n.angularVelocity[0] * lever0[1] - thisState_i->n.angularVelocity[1] * lever0[0]) + thisState_i->n.linearVelocity[2]) - + (FIXEDH(thisState_j->n.angularVelocity[0] * lever1[1] - thisState_j->n.angularVelocity[1] * lever1[0]) + thisState_j->n.linearVelocity[2]); - thisDelta[i].n.linearVelocity[0] = 0; - thisDelta[i].n.linearVelocity[1] = 0; - thisDelta[i].n.linearVelocity[2] = 0; - thisDelta[i].n.angularVelocity[0] = 0; - thisDelta[i].n.angularVelocity[1] = 0; - thisDelta[i].n.angularVelocity[2] = 0; + howHard = (pointVel0[0] / 256) * (normal[0] / 32) + + (pointVel0[1] / 256) * (normal[1] / 32) + + (pointVel0[2] / 256) * (normal[2] / 32); - for (j = 0; j < i; j++) + if (howHard > 0) { - c1 = active_car_list[j]; + if (DamageCar3D(c1, &lever1, howHard >> 1, cp)) + c1->ap.needsDenting = 1; - // [A] optimized run to not use the box checking - // as it has already composed bitfield / pairs - if((mayBeCollidingBits & (1 << CAR_INDEX(c1))) != 0 && (c1->hd.speed != 0 || cp->hd.speed != 0)) + if (DamageCar3D(cp, &lever0, howHard >> 1, c1)) + cp->ap.needsDenting = 1; + + if (howHard > 0x32000) + { + if (cp->controlType == CONTROL_TYPE_CIV_AI) + cp->ai.c.carMustDie = 1; + + if (c1->controlType == CONTROL_TYPE_CIV_AI) + c1->ai.c.carMustDie = 1; + } + + // wake up cops if they've ben touched + // [A] check player felony. + // If player touch them without felony player will be charged with felony (hit cop car) + if (numCopCars < 4 && numActiveCops < maxCopCars && GameType != GAME_GETAWAY && *felony >= FELONY_PURSUIT_MIN_VALUE) { - if(CarCarCollision3(cp, c1, &depth, (VECTOR*)collisionpoint, (VECTOR*)normal)) + if (cp->controlType == CONTROL_TYPE_PLAYER && IS_ROADBLOCK_CAR(c1)) { - if (RKstep > 0) - thisState_j = &_tp[j]; - else - thisState_j = &c1->st; - - int c1InfiniteMass; - int c2InfiniteMass; + InitCopState(c1, NULL); + c1->ai.p.justPinged = 0; + } - collisionpoint[1] -= 0; + if (c1->controlType == CONTROL_TYPE_PLAYER && IS_ROADBLOCK_CAR(cp)) + { + InitCopState(cp, NULL); + cp->ai.p.justPinged = 0; + } + } + + if (howHard > 0x1b00) + { + velocity.vy = -17; + velocity.vx = FIXED(cp->st.n.linearVelocity[0]); + velocity.vz = FIXED(cp->st.n.linearVelocity[2]); - lever0[0] = collisionpoint[0] - cp->hd.where.t[0]; - lever0[1] = collisionpoint[1] - cp->hd.where.t[1]; - lever0[2] = collisionpoint[2] - cp->hd.where.t[2]; + collisionpoint[1] = -collisionpoint[1]; - lever1[0] = collisionpoint[0] - c1->hd.where.t[0]; - lever1[1] = collisionpoint[1] - c1->hd.where.t[1]; - lever1[2] = collisionpoint[2] - c1->hd.where.t[2]; + if (cp->controlType == CONTROL_TYPE_PLAYER || c1->controlType == CONTROL_TYPE_PLAYER) + { + Setup_Sparks((VECTOR*)collisionpoint, &velocity, 6, 0); - strength = 47 - (lever0[1] + lever1[1]) / 2; + if (cp->controlType == CONTROL_TYPE_PLAYER) + SetPadVibration(*cp->ai.padid, 1); - lever0[1] += strength; - lever1[1] += strength; - - strikeVel = depth * 0xc000; - - pointVel0[0] = (FIXEDH(thisState_i->n.angularVelocity[1] * lever0[2] - thisState_i->n.angularVelocity[2] * lever0[1]) + thisState_i->n.linearVelocity[0]) - - (FIXEDH(thisState_j->n.angularVelocity[1] * lever1[2] - thisState_j->n.angularVelocity[2] * lever1[1]) + thisState_j->n.linearVelocity[0]); - - pointVel0[1] = (FIXEDH(thisState_i->n.angularVelocity[2] * lever0[0] - thisState_i->n.angularVelocity[0] * lever0[2]) + thisState_i->n.linearVelocity[1]) - - (FIXEDH(thisState_j->n.angularVelocity[2] * lever1[0] - thisState_j->n.angularVelocity[0] * lever1[2]) + thisState_j->n.linearVelocity[1]); - - pointVel0[2] = (FIXEDH(thisState_i->n.angularVelocity[0] * lever0[1] - thisState_i->n.angularVelocity[1] * lever0[0]) + thisState_i->n.linearVelocity[2]) - - (FIXEDH(thisState_j->n.angularVelocity[0] * lever1[1] - thisState_j->n.angularVelocity[1] * lever1[0]) + thisState_j->n.linearVelocity[2]); - - howHard = (pointVel0[0] / 256) * (normal[0] / 32) + - (pointVel0[1] / 256) * (normal[1] / 32) + - (pointVel0[2] / 256) * (normal[2] / 32); - - if (howHard > 0 && RKstep > -1) - { - if (DamageCar3D(c1, &lever1, howHard >> 1, cp)) - c1->ap.needsDenting = 1; - - if (DamageCar3D(cp, &lever0, howHard >> 1, c1)) - cp->ap.needsDenting = 1; - - if (howHard > 0x32000) - { - if (cp->controlType == CONTROL_TYPE_CIV_AI) - cp->ai.c.carMustDie = 1; - - if (c1->controlType == CONTROL_TYPE_CIV_AI) - c1->ai.c.carMustDie = 1; - } - - // wake up cops if they've ben touched - // [A] check player felony. - // If player touch them without felony player will be charged with felony (hit cop car) - if (numCopCars < 4 && numActiveCops < maxCopCars && GameType != GAME_GETAWAY && *felony >= FELONY_PURSUIT_MIN_VALUE) - { - if (cp->controlType == CONTROL_TYPE_PLAYER && IS_ROADBLOCK_CAR(c1)) - { - InitCopState(c1, NULL); - c1->ai.p.justPinged = 0; - } - - if (c1->controlType == CONTROL_TYPE_PLAYER && IS_ROADBLOCK_CAR(cp)) - { - InitCopState(cp, NULL); - cp->ai.p.justPinged = 0; - } - } - - if (howHard > 0x1b00) - { - velocity.vy = -17; - velocity.vx = FIXED(cp->st.n.linearVelocity[0]); - velocity.vz = FIXED(cp->st.n.linearVelocity[2]); - - collisionpoint[1] = -collisionpoint[1]; - - if (cp->controlType == CONTROL_TYPE_PLAYER || c1->controlType == CONTROL_TYPE_PLAYER) - { - Setup_Sparks((VECTOR*)collisionpoint, &velocity, 6, 0); - - if (cp->controlType == CONTROL_TYPE_PLAYER) - SetPadVibration(*cp->ai.padid, 1); - - if (c1->controlType == CONTROL_TYPE_PLAYER) - SetPadVibration(*c1->ai.padid, 1); - } - - if (howHard > 0x2400) - { - int debris1; - int debris2; - - debris1 = GetDebrisColour(cp); - debris2 = GetDebrisColour(c1); - - Setup_Debris((VECTOR*)collisionpoint, &velocity, 3, 0); - Setup_Debris((VECTOR*)collisionpoint, &velocity, 6, debris1 << 0x10); - Setup_Debris((VECTOR*)collisionpoint, &velocity, 2, debris2 << 0x10); - } - } - } - - strikeVel += (howHard * 9) / 4; - - if (strikeVel > 0x69000) - strikeVel = 0x69000; - - m1 = cp->ap.carCos->mass; - m2 = c1->ap.carCos->mass; - - if (m2 < m1) - { - do1 = (m2 * 4096) / m1; - do2 = 4096; - } - else - { - do2 = (m1 * 4096) / m2; - do1 = 4096; - } - - c1InfiniteMass = cp->controlType == CONTROL_TYPE_CUTSCENE || m1 == 0x7fff; - c2InfiniteMass = c1->controlType == CONTROL_TYPE_CUTSCENE || m2 == 0x7fff; - - // [A] if any checked cars has infinite mass, reduce bouncing - // TODO: very easy difficulty - if (c1InfiniteMass || c2InfiniteMass) - strikeVel = strikeVel * 10 >> 2; - - // apply force to car 0 - if (!c1InfiniteMass) - { - int twistY, strength1; - - if (cp->controlType == CONTROL_TYPE_PURSUER_AI && c1->controlType != CONTROL_TYPE_LEAD_AI && c1->hndType != 0) - strength1 = (strikeVel * (7 - gCopDifficultyLevel)) / 8; - else if (cp->controlType == CONTROL_TYPE_LEAD_AI && c1->hndType != 0) - strength1 = (strikeVel * 5) / 8; - else - strength1 = strikeVel; - - strength1 = FIXEDH(strength1) * do1 >> 3; - - velocity.vx = (normal[0] >> 3) * strength1 >> 6; - velocity.vz = (normal[2] >> 3) * strength1 >> 6; - velocity.vy = (normal[1] >> 3) * strength1 >> 6; - - thisDelta[i].n.linearVelocity[0] -= velocity.vx; - thisDelta[i].n.linearVelocity[1] -= velocity.vy; - thisDelta[i].n.linearVelocity[2] -= velocity.vz; - - twistY = car_cosmetics[cp->ap.model].twistRateY / 2; - - torque[0] = FIXEDH(velocity.vy * lever0[2] - velocity.vz * lever0[1]) * twistY; - torque[1] = FIXEDH(velocity.vz * lever0[0] - velocity.vx * lever0[2]) * twistY; - torque[2] = FIXEDH(velocity.vx * lever0[1] - velocity.vy * lever0[0]) * twistY; - - if (c1->controlType == CONTROL_TYPE_LEAD_AI) - { - torque[0] = 0; - torque[2] = 0; - } - - thisDelta[i].n.angularVelocity[0] += torque[0]; - thisDelta[i].n.angularVelocity[1] += torque[1]; - thisDelta[i].n.angularVelocity[2] += torque[2]; - } - - // apply force to car 1 - if (!c2InfiniteMass) - { - int twistY, strength2; - - if (cp->controlType == CONTROL_TYPE_PURSUER_AI && c1->controlType != CONTROL_TYPE_LEAD_AI && c1->hndType != 0) - strength2 = (strikeVel * (7 - gCopDifficultyLevel)) / 8; - else if (c1->controlType == CONTROL_TYPE_LEAD_AI && cp->hndType != 0) - strength2 = (strikeVel * 5) / 8; - else - strength2 = strikeVel; - - strength2 = FIXEDH(strength2) * do2 >> 3; - - velocity.vx = (normal[0] >> 3) * strength2 >> 6; - velocity.vy = (normal[1] >> 3) * strength2 >> 6; - velocity.vz = (normal[2] >> 3) * strength2 >> 6; - - thisDelta[j].n.linearVelocity[0] += velocity.vx; - thisDelta[j].n.linearVelocity[1] += velocity.vy; - thisDelta[j].n.linearVelocity[2] += velocity.vz; - - twistY = car_cosmetics[c1->ap.model].twistRateY / 2; - - torque[0] = FIXEDH(lever1[1] * velocity.vz - lever1[2] * velocity.vy) * twistY; - torque[1] = FIXEDH(lever1[2] * velocity.vx - lever1[0] * velocity.vz) * twistY; - torque[2] = FIXEDH(lever1[0] * velocity.vy - lever1[1] * velocity.vx) * twistY; - - if (c1->controlType == CONTROL_TYPE_LEAD_AI) - { - torque[0] = 0; - torque[2] = 0; - } - - thisDelta[j].n.angularVelocity[0] += torque[0]; - thisDelta[j].n.angularVelocity[1] += torque[1]; - thisDelta[j].n.angularVelocity[2] += torque[2]; - } - - if (cp->id == player[0].playerCarId || c1->id == player[0].playerCarId) - RegisterChaseHit(cp->id, c1->id); - - if (cp->id == player[0].playerCarId) - CarHitByPlayer(c1, howHard); - - if (c1->id == player[0].playerCarId) - CarHitByPlayer(cp, howHard); + if (c1->controlType == CONTROL_TYPE_PLAYER) + SetPadVibration(*c1->ai.padid, 1); } - } // maybe colliding - } // j loop - } - } - // update forces and rebuild matrix of the cars - for (i = 0; i < num_active_cars; i++) - { - cp = active_car_list[i]; + if (howHard > 0x2400) + { + int debris1; + int debris2; - // if has any collision, process with double precision - if (cp->hd.mayBeColliding) - { - st = &cp->st; - tp = &_tp[i]; - d0 = &_d0[i]; - d1 = &_d1[i]; + debris1 = GetDebrisColour(cp); + debris2 = GetDebrisColour(c1); + + Setup_Debris((VECTOR*)collisionpoint, &velocity, 3, 0); + Setup_Debris((VECTOR*)collisionpoint, &velocity, 6, debris1 << 0x10); + Setup_Debris((VECTOR*)collisionpoint, &velocity, 2, debris2 << 0x10); + } + } + } + + strikeVel += (howHard * 9) / 4; + + if (strikeVel > 0x69000) + strikeVel = 0x69000; + + m1 = cp->ap.carCos->mass; + m2 = c1->ap.carCos->mass; - if (RKstep == 0) + if (m2 < m1) { - for (j = 0; j < 13; j++) + do1 = (m2 * 4096) / m1; + do2 = 4096; + } + else + { + do2 = (m1 * 4096) / m2; + do1 = 4096; + } + + c1InfiniteMass = cp->controlType == CONTROL_TYPE_CUTSCENE || m1 == 0x7fff; + c2InfiniteMass = c1->controlType == CONTROL_TYPE_CUTSCENE || m2 == 0x7fff; + + // [A] if any checked cars has infinite mass, reduce bouncing + // TODO: very easy difficulty + if (c1InfiniteMass || c2InfiniteMass) + strikeVel = strikeVel * 10 >> 2; + + // apply force to car 0 + if (!c1InfiniteMass) + { + int twistY, strength1; + + if (cp->controlType == CONTROL_TYPE_PURSUER_AI && c1->controlType != CONTROL_TYPE_LEAD_AI && c1->hndType != 0) + strength1 = (strikeVel * (7 - gCopDifficultyLevel)) / 8; + else if (cp->controlType == CONTROL_TYPE_LEAD_AI && c1->hndType != 0) + strength1 = (strikeVel * 5) / 8; + else + strength1 = strikeVel; + + strength1 = FIXEDH(strength1) * do1 >> 3; + + velocity.vx = (normal[0] >> 3) * strength1 >> 6; + velocity.vz = (normal[2] >> 3) * strength1 >> 6; + velocity.vy = (normal[1] >> 3) * strength1 >> 6; + + thisDelta[i].n.linearVelocity[0] -= velocity.vx; + thisDelta[i].n.linearVelocity[1] -= velocity.vy; + thisDelta[i].n.linearVelocity[2] -= velocity.vz; + + twistY = car_cosmetics[cp->ap.model].twistRateY / 2; + + torque[0] = FIXEDH(velocity.vy * lever0[2] - velocity.vz * lever0[1]) * twistY; + torque[1] = FIXEDH(velocity.vz * lever0[0] - velocity.vx * lever0[2]) * twistY; + torque[2] = FIXEDH(velocity.vx * lever0[1] - velocity.vy * lever0[0]) * twistY; + + if (c1->controlType == CONTROL_TYPE_LEAD_AI) { - tp->v[j] = st->v[j] + (d0->v[j] >> 2); + torque[0] = 0; + torque[2] = 0; } - RebuildCarMatrix(tp, cp); + thisDelta[i].n.angularVelocity[0] += torque[0]; + thisDelta[i].n.angularVelocity[1] += torque[1]; + thisDelta[i].n.angularVelocity[2] += torque[2]; } - else if (RKstep == 1) + + // apply force to car 1 + if (!c2InfiniteMass) { - for (j = 0; j < 13; j++) + int twistY, strength2; + + if (cp->controlType == CONTROL_TYPE_PURSUER_AI && c1->controlType != CONTROL_TYPE_LEAD_AI && c1->hndType != 0) + strength2 = (strikeVel * (7 - gCopDifficultyLevel)) / 8; + else if (c1->controlType == CONTROL_TYPE_LEAD_AI && cp->hndType != 0) + strength2 = (strikeVel * 5) / 8; + else + strength2 = strikeVel; + + strength2 = FIXEDH(strength2) * do2 >> 3; + + velocity.vx = (normal[0] >> 3) * strength2 >> 6; + velocity.vy = (normal[1] >> 3) * strength2 >> 6; + velocity.vz = (normal[2] >> 3) * strength2 >> 6; + + thisDelta[j].n.linearVelocity[0] += velocity.vx; + thisDelta[j].n.linearVelocity[1] += velocity.vy; + thisDelta[j].n.linearVelocity[2] += velocity.vz; + + twistY = car_cosmetics[c1->ap.model].twistRateY / 2; + + torque[0] = FIXEDH(lever1[1] * velocity.vz - lever1[2] * velocity.vy) * twistY; + torque[1] = FIXEDH(lever1[2] * velocity.vx - lever1[0] * velocity.vz) * twistY; + torque[2] = FIXEDH(lever1[0] * velocity.vy - lever1[1] * velocity.vx) * twistY; + + if (c1->controlType == CONTROL_TYPE_LEAD_AI) { - st->v[j] += d0->v[j] + d1->v[j] >> 3; + torque[0] = 0; + torque[2] = 0; } - RebuildCarMatrix(st, cp); + thisDelta[j].n.angularVelocity[0] += torque[0]; + thisDelta[j].n.angularVelocity[1] += torque[1]; + thisDelta[j].n.angularVelocity[2] += torque[2]; + } + + if (cp->id == player[0].playerCarId || c1->id == player[0].playerCarId) + RegisterChaseHit(cp->id, c1->id); + + if (cp->id == player[0].playerCarId) + CarHitByPlayer(c1, howHard); + + if (c1->id == player[0].playerCarId) + CarHitByPlayer(cp, howHard); + + } // j loop + } // i loop + + // update forces and rebuild matrix of the cars + for (i = 0; i < num_active_cars; i++) + { + cp = active_car_list[i]; + + // if has any collision, process with double precision + if (cp->hd.mayBeColliding == 0) + { + continue; + } + + st = &cp->st; + tp = &_tp[i]; + d0 = &_d0[i]; + d1 = &_d1[i]; + + if (RKstep == 0) + { + for (j = 0; j < 13; j++) + { + tp->v[j] = st->v[j] + (d0->v[j] >> 2); } + + RebuildCarMatrix(tp, cp); + } + else if (RKstep == 1) + { + for (j = 0; j < 13; j++) + { + st->v[j] += d0->v[j] + d1->v[j] >> 3; + } + + RebuildCarMatrix(st, cp); } } } } - - // second sub frame passed, update matrices and physics direction // dent cars - no more than 5 cars in per frame carsDentedThisFrame = 0; @@ -751,9 +748,6 @@ void GlobalTimeStep(void) void SetShadowPoints(CAR_DATA* c0, VECTOR* outpoints) { int i; - SVECTOR disp; - VECTOR pointPos; - VECTOR surfaceNormal; CAR_COSMETICS* car_cos; sdPlane* surfacePtr; @@ -766,15 +760,10 @@ void SetShadowPoints(CAR_DATA* c0, VECTOR* outpoints) for (i = 0; i < 4; i++) { - disp = car_cos->cPoints[i]; - - gte_ldv0(&disp); - + gte_ldv0(&car_cos->cPoints[i]); gte_rtv0tr(); - - gte_stlvnl(&pointPos); - - FindSurfaceD2(&pointPos, &surfaceNormal, &outpoints[i], &surfacePtr); + gte_stlvnl(&outpoints[i]); + outpoints[i].vy = MapHeight(&outpoints[i]); } } @@ -864,12 +853,8 @@ void initOBox(CAR_DATA* cp) // [D] [T] void RebuildCarMatrix(RigidBodyState* st, CAR_DATA* cp) { - int sm; - int osm; - int qw; - int qz; - int qy; - int qx; + int sm, osm; + int qw, qz, qy, qx; cp->hd.where.t[0] = st->n.fposition[0] >> 4; cp->hd.where.t[1] = st->n.fposition[1] >> 4; @@ -978,9 +963,7 @@ void CheckCarToCarCollisions(void) int lbod, wbod, hbod; int xx, zz; - BOUND_BOX* bb; - BOUND_BOX* bb2; - BOUND_BOX* bb1; + BOUND_BOX* bb, *bb1, *bb2; CAR_DATA* cp; SVECTOR* colBox; @@ -1523,7 +1506,9 @@ void CheckCarEffects(CAR_DATA* cp, int player_id) rear_vel = ABS(cp->hd.rear_vel); front_vel = ABS(cp->hd.front_vel); - if ((wheels_on_ground & 5) && (rear_vel > 15000 || cp->wheelspin)) + const int front_wh = 0x1 | 0x4; + const int rear_wh = 0x2 | 0x8; + if ((wheels_on_ground & 10) && (rear_vel > 15000 || cp->wheelspin)) { lay_down_tracks |= 1; @@ -1536,7 +1521,7 @@ void CheckCarEffects(CAR_DATA* cp, int player_id) skidsound = 13000; } - if ((wheels_on_ground & 10) && front_vel > 15000) + if ((wheels_on_ground & 5) && front_vel > 15000) { lay_down_tracks |= 2; } @@ -1677,18 +1662,18 @@ void CheckCarEffects(CAR_DATA* cp, int player_id) if (lay_down_tracks & 1) // rear { #if MAX_TYRE_TRACK_WHEELS == 4 - ADD_WHEEL_TYRE_TRACK(0, 0) - ADD_WHEEL_TYRE_TRACK(2, 2) + ADD_WHEEL_TYRE_TRACK(1, 1) + ADD_WHEEL_TYRE_TRACK(3, 3) #else - ADD_WHEEL_TYRE_TRACK(0, 0) - ADD_WHEEL_TYRE_TRACK(2, 1) + ADD_WHEEL_TYRE_TRACK(1, 0) + ADD_WHEEL_TYRE_TRACK(3, 1) #endif } else { #if MAX_TYRE_TRACK_WHEELS == 4 - last_track_state[player_id][0] = -1; - last_track_state[player_id][2] = -1; + last_track_state[player_id][1] = -1; + last_track_state[player_id][3] = -1; #else last_track_state[player_id][0] = -1; last_track_state[player_id][1] = -1; @@ -1698,13 +1683,13 @@ void CheckCarEffects(CAR_DATA* cp, int player_id) #if MAX_TYRE_TRACK_WHEELS == 4 if (lay_down_tracks & 2) // front { - ADD_WHEEL_TYRE_TRACK(1, 1) - ADD_WHEEL_TYRE_TRACK(3, 3) + ADD_WHEEL_TYRE_TRACK(0, 0) + ADD_WHEEL_TYRE_TRACK(2, 2) } else { - last_track_state[player_id][1] = -1; - last_track_state[player_id][3] = -1; + last_track_state[player_id][0] = -1; + last_track_state[player_id][2] = -1; } #endif diff --git a/src_rebuild/Game/C/leadai.c b/src_rebuild/Game/C/leadai.c index 4f6fddde0..dc2d06d9b 100644 --- a/src_rebuild/Game/C/leadai.c +++ b/src_rebuild/Game/C/leadai.c @@ -1522,9 +1522,7 @@ void UpdateRoadPosition(CAR_DATA* cp, VECTOR* basePos, int intention) if (RoadMapRegions[cbr] != cbrX + cbrZ * regions_across) continue; - ppco = GetFirstPackedCop(cell_x, cell_z, &ci, 1); - - while (ppco) + for (ppco = GetFirstPackedCop(cell_x, cell_z, &ci, 1); ppco; ppco = GetNextPackedCop(&ci)) { int type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10); model = modelpointers[type]; @@ -1666,7 +1664,6 @@ void UpdateRoadPosition(CAR_DATA* cp, VECTOR* basePos, int intention) collide++; } } - ppco = GetNextPackedCop(&ci); } } } @@ -2819,8 +2816,9 @@ u_int hypot(int x, int y) if (x < y) { + t = y; y = x; - x = y; + x = t; } if (x < 0x8000) diff --git a/src_rebuild/Game/C/loadview.c b/src_rebuild/Game/C/loadview.c index 3658dada4..0a500a5ae 100644 --- a/src_rebuild/Game/C/loadview.c +++ b/src_rebuild/Game/C/loadview.c @@ -177,7 +177,7 @@ void ShowLoadingScreen(char *screen_name, int effect, int loading_steps) DrawSync(0); setRECT(&dest, 320, 0, 160, 511); - LoadImage(&dest, (u_long *)&_other_buffer[544]); + LoadImage(&dest, (u_long*)&_other_buffer[544]); DrawSync(0); @@ -418,8 +418,8 @@ void DrawFadePoly(void) setRGB2(fl_g4, fadeVal, fadeVal, fadeVal); setRGB3(fl_g4, fadeVal, fadeVal, fadeVal); - addPrim(¤t->ot[1], fl_g4); - addPrim(¤t->ot[1], &fade_gt4[current->id]); + addPrim(current->ot + 1, fl_g4); + addPrim(current->ot + 1, &fade_gt4[current->id]); } // [D] [T] diff --git a/src_rebuild/Game/C/main.c b/src_rebuild/Game/C/main.c index 54a3ab617..6405104c5 100644 --- a/src_rebuild/Game/C/main.c +++ b/src_rebuild/Game/C/main.c @@ -388,14 +388,14 @@ void LoadGameLevel(void) if (gMultiplayerLevels == 0) { - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) SetCityType(CITYTYPE_NIGHT); else SetCityType(CITYTYPE_DAY); } else { - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) SetCityType(CITYTYPE_MULTI_NIGHT); else SetCityType(CITYTYPE_MULTI_DAY); @@ -619,7 +619,7 @@ void State_GameInit(void* param) InitMap(); InitSpecSpool(); - if ((NewLevel == 0 || gCarCleanModelPtr[4] == NULL) && allowSpecSpooling == 1) // [A] to load even more secret truck from Chicago + if (NewLevel == 0 && allowSpecSpooling == 1) { QuickSpoolSpecial(); } @@ -694,14 +694,12 @@ void State_GameInit(void* param) FrAng = 512; - if (gWeather == 1) + if (gWeather == WEATHER_RAIN) wetness = 7000; - //else if (gWeather == 2) // [A] addition that I have disabled - // wetness = 3000; else wetness = 0; - if (gTimeOfDay == 2) + if (gTimeOfDay == TIME_DUSK) { for ( i = 0; i < MAX_CARS; i++) lightsOnDelay[i] = (i * 11); @@ -840,7 +838,6 @@ void StepSim(void) static u_int t0; // offset 0x0 static char t1; // offset 0x4 static char t2; // offset 0x5 - static int oldsp; // offset 0x8 char padAcc; short* playerFelony; @@ -849,8 +846,9 @@ void StepSim(void) PLAYER* pl; int i, j; int car; + int timeOfDay; - if (gTimeOfDay == 0 || gTimeOfDay == 2) + if (M_BIT(gTimeOfDay) & (M_BIT(TIME_DAWN) | M_BIT(TIME_DUSK))) { DawnCount++; } @@ -871,8 +869,6 @@ void StepSim(void) pauseflag = 1; } - //oldsp = SetSp((u_long)((u_char*)getScratchAddr(0) + 0x3e8)); // i don't know what this does - lead_pad = (u_int)controller_bits; if (player[0].playerCarId < 0) @@ -1148,8 +1144,6 @@ void StepSim(void) DoScenaryCollisions(); CheckPlayerMiscFelonies(); - //SetSp(oldsp); - CameraCnt++; pl = player; @@ -1299,7 +1293,7 @@ void StepGame(void) ControlMap(); } - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) PreLampStreak(); if ((padd & 0x2000U) && (padd & 0x8000U)) @@ -1321,7 +1315,7 @@ void StepGame(void) lis_pos = camera_position; // update colours of ambience - if (gTimeOfDay == 0) + if (gTimeOfDay == TIME_DAWN) { NightAmbient = (DawnCount >> 7) + 26; gLightsOn = (DawnCount < 4000); @@ -1329,7 +1323,7 @@ void StepGame(void) if (NightAmbient > 96) NightAmbient = 96; } - else if (gTimeOfDay == 1) + else if (gTimeOfDay == TIME_DAY) { gLightsOn = 0; @@ -1338,7 +1332,7 @@ void StepGame(void) else NightAmbient = 78; } - else if (gTimeOfDay == 2) + else if (gTimeOfDay == TIME_DUSK) { if (DawnCount < 3000) { @@ -1363,13 +1357,13 @@ void StepGame(void) if (NightAmbient < 45) NightAmbient = 45; } - else if (gTimeOfDay == 3) + else if (gTimeOfDay == TIME_NIGHT) { gLightsOn = 1; NightAmbient = 128; } - if (gWeather != 0 && gWeather == 1) + if (gWeather == WEATHER_RAIN) { DoLightning(); DoThunder(); @@ -1610,9 +1604,7 @@ void State_GameLoop(void* param) _CutRec_Step(); } -// TODO: DRAW.C? int ObjectDrawnValue = 0; -int ObjectDrawnCounter = 0; // [D] [T] void DrawGame(void) @@ -1623,26 +1615,19 @@ void DrawGame(void) DrawPauseMenus(); RenderGame2(0); - - ObjectDrawnCounter++; - SwapDrawBuffers(); } else { ObjectDrawnValue = FrameCnt; RenderGame2(0); - ObjectDrawnCounter++; - SwapDrawBuffers2(0); ObjectDrawnValue += 16; - + DrawPauseMenus(); RenderGame2(1); - ObjectDrawnCounter++; - SwapDrawBuffers2(1); } @@ -2387,6 +2372,11 @@ void RenderGame2(int view) DrawAllTheCars(view); #ifndef PSX + +#ifdef DYNAMIC_LIGHTING + gNumDlights = 0; +#endif + extern void DrawDebugOverlays(); DrawDebugOverlays(); @@ -2542,7 +2532,7 @@ void DealWithHorn(char* hr, int i) *hr = (*hr + 1) % 3; } -// [D] [T] [A] Has bugs - some rooms not drawn properly +// [D] [T] int Havana3DOcclusion(occlFunc func, int* param) { int loop; diff --git a/src_rebuild/Game/C/main.h b/src_rebuild/Game/C/main.h index d1da426b1..f07ec1320 100644 --- a/src_rebuild/Game/C/main.h +++ b/src_rebuild/Game/C/main.h @@ -22,9 +22,7 @@ extern int wetness; extern int scr_z; extern int DawnCount; - extern int ObjectDrawnValue; -extern int ObjectDrawnCounter; extern int Havana3DLevelDraw; diff --git a/src_rebuild/Game/C/map.c b/src_rebuild/Game/C/map.c index 0ed0bd525..a65f7e628 100644 --- a/src_rebuild/Game/C/map.c +++ b/src_rebuild/Game/C/map.c @@ -98,10 +98,9 @@ void ProcessMapLump(char* lump_ptr, int lump_size) trap(0x400); } #endif - - view_dist = 10; - pvs_square = 21; - pvs_square_sq = 21 * 21; + view_dist = PVS_CELL_COUNT / 2; + pvs_square = PVS_CELL_COUNT; + pvs_square_sq = PVS_CELL_COUNT * PVS_CELL_COUNT; units_across_halved = cells_across / 2 * MAP_CELL_SIZE; units_down_halved = cells_down / 2 * MAP_CELL_SIZE; @@ -167,50 +166,20 @@ int newPositionVisible(VECTOR *pos, char *pvs, int ccx, int ccz) cellx = (dx / MAP_CELL_SIZE) - ccx; cellz = (dz / MAP_CELL_SIZE) - ccz; - if (ABS(cellx) <= view_dist && ABS(cellz) <= view_dist) - { - return pvs[cellx + 10 + (cellz + 10) * pvs_square] != 0; - } - - return 0; -} - -// [D] [T] -int PositionVisible(VECTOR *pos) -{ - int dx; // $a1 - int dz; // $a0 - int cellx; // $v1 - int cellz; // $v0 - - int ab; - - dx = pos->vx + units_across_halved; - dz = pos->vz + units_down_halved; - - cellx = (dx / MAP_CELL_SIZE) - current_cell_x; - cellz = (dz / MAP_CELL_SIZE) - current_cell_z; - - if (cellx < 0) - ab = -cellx; - else - ab = cellx; +#ifndef PSX + cellx = MIN(MAX(cellx, -9), PVS_CELL_COUNT / 2); + cellz = MIN(MAX(cellz, -9), PVS_CELL_COUNT / 2); +#endif // PSX - if (ab <= view_dist) + if (ABS(cellx) <= view_dist && + ABS(cellz) <= view_dist) { - if (cellz < 0) - ab = -cellz; - else - ab = cellz; - - if (ab <= view_dist) - return CurrentPVS[cellx + 10 + (cellz + 10) * pvs_square] != 0; + return pvs[cellx + 10 + (cellz + 10) * pvs_square] != 0; } return 0; } - // FIXME: move it somewhere else extern int saved_leadcar_pos; diff --git a/src_rebuild/Game/C/map.h b/src_rebuild/Game/C/map.h index b38a0ae2c..d9f2242a4 100644 --- a/src_rebuild/Game/C/map.h +++ b/src_rebuild/Game/C/map.h @@ -1,6 +1,8 @@ #ifndef MAP_H #define MAP_H +#define PVS_CELL_COUNT 21 // cells. Do not modify + #ifdef PSX // original Driver 2 definition @@ -73,7 +75,6 @@ extern void ProcessJuncBoundsLump(char *lump_file, int lump_size); // 0x0005D6DC extern void ProcessMapLump(char* lump_ptr, int lump_size); // 0x00040608 extern int newPositionVisible(VECTOR *pos, char *pvs, int ccx, int ccz); // 0x0005D61C -extern int PositionVisible(VECTOR *pos); // 0x0005D560 extern void ControlMap(); // 0x0005CC00 extern void GetVisSetAtPosition(VECTOR *pos, char *tgt, int *ccx, int *ccz); // 0x0005D6E4 diff --git a/src_rebuild/Game/C/mc_snd.c b/src_rebuild/Game/C/mc_snd.c index b70b14170..22ac154ff 100644 --- a/src_rebuild/Game/C/mc_snd.c +++ b/src_rebuild/Game/C/mc_snd.c @@ -665,7 +665,7 @@ void DoMissionSound(void) else { int dx, dz; - long* C = (long*)bodgevar; // Ahhh, Reflections... // LONGVECTOR3 + int* C = (int*)bodgevar; // Ahhh, Reflections... // LONGVECTOR3 dx = C[0] - car_data[player[0].playerCarId].hd.where.t[0]; dz = C[2] - car_data[player[0].playerCarId].hd.where.t[2]; diff --git a/src_rebuild/Game/C/mdraw.c b/src_rebuild/Game/C/mdraw.c index a234ca381..7b23e3977 100644 --- a/src_rebuild/Game/C/mdraw.c +++ b/src_rebuild/Game/C/mdraw.c @@ -159,7 +159,7 @@ void DrawOverheadTarget(MS_TARGET *target) break; } case Target_Event: // event target - tv = *target->s.event.eventPos; + tv = *(*(VECTOR**)&target->s.event.eventPos); break; default: return; @@ -194,7 +194,7 @@ void DrawFullscreenTarget(MS_TARGET *target) break; } case Target_Event: // event target - tv = *target->s.event.eventPos; + tv = *(*(VECTOR**)&target->s.event.eventPos); break; default: return; @@ -297,7 +297,7 @@ void DrawWorldTarget(MS_TARGET *target) } case Target_Event: { - tv = *target->s.event.eventPos; + tv = *(*(VECTOR**)&target->s.event.eventPos); break; } default: @@ -414,7 +414,7 @@ void DrawMultiplayerTarget(MS_TARGET *target) } case Target_Event: { - tv = *target->s.event.eventPos; + tv = *(*(VECTOR**)&target->s.event.eventPos); break; } default: diff --git a/src_rebuild/Game/C/mission.c b/src_rebuild/Game/C/mission.c index 414a2e069..dee72be54 100644 --- a/src_rebuild/Game/C/mission.c +++ b/src_rebuild/Game/C/mission.c @@ -151,8 +151,8 @@ MS_MISSION* MissionHeader; STREAM_SOURCE* PlayerStartInfo[8]; int numPlayersToCreate = 0; int gStartOnFoot = 0; -int gWeather = 0; -int gTimeOfDay = 0; +int gWeather = WEATHER_NONE; +int gTimeOfDay = TIME_DAY; int gShowPlayerDamage = 0; int gDontPingInCops = 0; int gBatterPlayer = 1; @@ -263,7 +263,7 @@ void InitialiseMissionDefaults(void) prevCopsInPursuit = 0; - for (i = 0; i < 15; i++) + for (i = 0; i < MAX_MISSION_THREADS; i++) { MissionThreads[i].initial_sp = MissionStack[i]; MissionThreads[i].active = 0; @@ -436,12 +436,12 @@ void LoadMission(int missionnum) LoadfileSeg(filename, (char *)MissionLoadAddress, offset, sizeof(MS_MISSION)); MissionHeader = MissionLoadAddress; - MissionTargets = (MS_TARGET *)((int)MissionLoadAddress + MissionLoadAddress->size); + MissionTargets = (MS_TARGET *)((char*)MissionLoadAddress + MissionLoadAddress->size); MissionScript = (u_int *)(MissionTargets + MAX_MISSION_TARGETS); - MissionStrings = (char*)((int*)MissionScript + MissionLoadAddress->strings); + MissionStrings = (char*)(MissionScript + MissionLoadAddress->strings); if (MissionLoadAddress->route && !NewLevel) - loadsize = (int)MissionStrings + (MissionLoadAddress->route - (int)MissionLoadAddress); + loadsize = (u_int)((char*)MissionStrings + ((char*)MissionLoadAddress->route - (char*)MissionLoadAddress)); else loadsize = length; @@ -514,13 +514,13 @@ void LoadMission(int missionnum) if (wantedWeather > -1) gWeather = wantedWeather; - if (gTimeOfDay >= 3) + if (gTimeOfDay >= TIME_NIGHT) gNight = 1; else gNight = 0; // setup weather - if (gWeather == 1) + if (gWeather == WEATHER_RAIN) { gRainCount = 30; gEffectsTimer = 41; @@ -1386,6 +1386,7 @@ int Swap2Cars(int curslot, int newslot) gDontResetCarDamage = 0; +#if ENABLE_GAME_FIXES // [A] swap cars in targets and fix "Bank Job" bug for (int i = 0; i < MAX_MISSION_TARGETS; i++) { @@ -1399,6 +1400,7 @@ int Swap2Cars(int curslot, int newslot) swapTgt->s.car.slot = curslot; } } +#endif return newslot; } @@ -1670,7 +1672,7 @@ int MRCommand(MR_THREAD *thread, u_int cmd) else if (cmd == 0x1000090) // SetRaining { MR_DebugWarn("MR %d command: SetRaining\n", thread - MissionThreads); - gWeather = 1; + gWeather = WEATHER_RAIN; return 1; } else if (cmd == 0x1000040) @@ -2565,7 +2567,7 @@ int MRProcessTarget(MR_THREAD *thread, MS_TARGET *target) if (target->s.target_flags & TARGET_FLAG_EVENT_TRIGGERED) { // [A] Ahhhh, 32 bit pointers... for future full-scale refactoring - if (target->s.event.loseMessage != -1 && Long2DDistance(target->s.event.eventPos, &pv) > 30000) + if (target->s.event.loseMessage != -1 && Long2DDistance((*(VECTOR**)&target->s.event.eventPos), &pv) > 30000) { message = MissionStrings + target->s.event.loseMessage; SetPlayerMessage(thread->player, message, 2, 2); @@ -2574,7 +2576,7 @@ int MRProcessTarget(MR_THREAD *thread, MS_TARGET *target) } else { - target->s.event.eventPos = TriggerEvent(target->s.event.eventId); + (*(VECTOR**)&target->s.event.eventPos) = TriggerEvent(target->s.event.eventId); target->s.target_flags |= TARGET_FLAG_EVENT_TRIGGERED; } @@ -2967,6 +2969,7 @@ void CompleteAllActiveTargets(int player) if (pTarget->type >= Target_Point && pTarget->type <= Target_Event && (pTarget->s.target_flags & flag1)) { + pTarget->s.target_flags &= ~flag1; pTarget->s.target_flags |= flag2; } } diff --git a/src_rebuild/Game/C/models.c b/src_rebuild/Game/C/models.c index 06911349c..987ee1303 100644 --- a/src_rebuild/Game/C/models.c +++ b/src_rebuild/Game/C/models.c @@ -5,6 +5,10 @@ #include "mission.h" #include "cars.h" +#if USE_PC_FILESYSTEM +extern int gContentOverride; +#endif + MODEL dummyModel = { 0 }; char* modelname_buffer = NULL; @@ -20,6 +24,7 @@ u_short *Low2LowerDetailTable = NULL; // [A] int staticModelSlotBitfield[48]; +int litSprites[48]; // [A] returns freed slot count int CleanSpooledModelSlots() @@ -39,6 +44,7 @@ int CleanSpooledModelSlots() { modelpointers[i] = &dummyModel; pLodModels[i] = &dummyModel; + litSprites[i >> 5] &= ~(1 << (i & 31)); num_freed++; } @@ -48,6 +54,25 @@ int CleanSpooledModelSlots() return num_freed; } +// [A] +void ProcessModel(int modelIdx) +{ + MODEL* model; + + model = modelpointers[modelIdx]; + + model->tri_verts = 0; // [A] this is used as additional flags for animated models and triangle processing + + if (gTimeOfDay == TIME_NIGHT) + { + if (model->shape_flags & SHAPE_FLAG_SPRITE) + { + if (modelIdx != 1223 && (!(model->flags2 & MODEL_FLAG_TREE) || modelIdx == 945 || modelIdx == 497)) + litSprites[modelIdx >> 5] |= 1 << (modelIdx & 31); + } + } +} + // [D] [T] void ProcessMDSLump(char *lump_file, int lump_size) { @@ -56,6 +81,7 @@ void ProcessMDSLump(char *lump_file, int lump_size) MODEL *parentmodel; int modelAmts; int i, size; + int litModel; modelAmts = *(int *)lump_file; mdsfile = (lump_file + 4); @@ -63,6 +89,7 @@ void ProcessMDSLump(char *lump_file, int lump_size) // [A] usage bits ClearMem((char*)staticModelSlotBitfield, sizeof(staticModelSlotBitfield)); + ClearMem((char*)litSprites, sizeof(litSprites)); // assign model pointers for (i = 0; i < MAX_MODEL_SLOTS; i++) // [A] bug fix. Init with dummyModel @@ -83,6 +110,8 @@ void ProcessMDSLump(char *lump_file, int lump_size) model = (MODEL*)mdsfile; modelpointers[i] = model; + + ProcessModel(i); } mdsfile += size; @@ -216,11 +245,47 @@ int ProcessCarModelLump(char *lump_ptr, int lump_size) int cleanOfs = offsets[0]; int damOfs = offsets[1]; int lowOfs = offsets[2]; + +#if USE_PC_FILESYSTEM + if (gContentOverride) + { + char* mem; + if (mem = LoadCarModelFromFile(NULL, model_number, CAR_MODEL_CLEAN)) + { + D_MALLOC_BEGIN(); + model = GetCarModel(mem, (char**)&mallocptr, 1); + D_MALLOC_END(); + + gCarCleanModelPtr[i] = model; + cleanOfs = -1; // skip loading + } + + if (mem = LoadCarModelFromFile(NULL, model_number, CAR_MODEL_DAMAGED)) + { + D_MALLOC_BEGIN(); + model = GetCarModel(mem, (char**)&mallocptr, 1); + D_MALLOC_END(); + + gCarDamModelPtr[i] = model; + damOfs = -1; // skip loading + } + + if (mem = LoadCarModelFromFile(NULL, model_number, CAR_MODEL_LOWDETAIL)) + { + D_MALLOC_BEGIN(); + model = GetCarModel(mem, (char**)&mallocptr, 1); + D_MALLOC_END(); + + gCarLowModelPtr[i] = model; + lowOfs = -1; // skip loading + } + } +#endif if (cleanOfs != -1) { D_MALLOC_BEGIN(); - model = GetCarModel(models_offset + cleanOfs, (char**)&mallocptr, 1, model_number, CAR_MODEL_CLEAN); + model = GetCarModel(models_offset + cleanOfs, (char**)&mallocptr, 1); gCarCleanModelPtr[i] = model; D_MALLOC_END(); } @@ -228,7 +293,7 @@ int ProcessCarModelLump(char *lump_ptr, int lump_size) if (damOfs != -1) { D_MALLOC_BEGIN(); - model = GetCarModel(models_offset + damOfs, (char**)&mallocptr, 0, model_number, CAR_MODEL_DAMAGED); + model = GetCarModel(models_offset + damOfs, (char**)&mallocptr, 0); gCarDamModelPtr[i] = model; D_MALLOC_END(); } @@ -236,7 +301,7 @@ int ProcessCarModelLump(char *lump_ptr, int lump_size) if (lowOfs != -1) { D_MALLOC_BEGIN(); - model = GetCarModel(models_offset + lowOfs, (char**)&mallocptr, 1, model_number, CAR_MODEL_LOWDETAIL); + model = GetCarModel(models_offset + lowOfs, (char**)&mallocptr, 1); gCarLowModelPtr[i] = model; D_MALLOC_END(); } @@ -244,6 +309,15 @@ int ProcessCarModelLump(char *lump_ptr, int lump_size) } D_MALLOC_BEGIN(); + +#if USE_PC_FILESYSTEM + if (gContentOverride) + { + // extra spool memory needed + specMemReq += 4096; + } +#endif + mallocptr = specmallocptr + specMemReq; specLoadBuffer = specmallocptr + specMemReq - 2048; D_MALLOC_END(); @@ -260,14 +334,14 @@ char* CarModelTypeNames[] = { "LOW", }; -#ifndef PSX +#if USE_PC_FILESYSTEM // [A] loads car model from file char* LoadCarModelFromFile(char* dest, int modelNumber, int type) { char* mem; char filename[64]; - sprintf(filename, "LEVELS\\%s\\CARMODEL_%d_%s.DMODEL", LevelNames[GameLevel], modelNumber, CarModelTypeNames[type-1]); + sprintf(filename, "LEVELS\\%s\\CARMODEL_%d_%s.MDL", LevelNames[GameLevel], modelNumber, CarModelTypeNames[type-1]); if(FileExists(filename)) { mem = (char*)(dest ? dest : (_other_buffer + modelNumber * 0x10000 + (type-1) * 0x4000)); @@ -282,30 +356,21 @@ char* LoadCarModelFromFile(char* dest, int modelNumber, int type) #endif // [D] [T] -MODEL* GetCarModel(char *src, char **dest, int KeepNormals, int modelNumber, int type) +MODEL* GetCarModel(char *src, char **dest, int KeepNormals) { int size; MODEL *model; char* mem; - -#ifndef PSX - mem = LoadCarModelFromFile(NULL, modelNumber, type); - - if (!mem) // fallback to lump - mem = src; -#else - mem = src; -#endif model = (MODEL *)*dest; if (KeepNormals == 0) - size = ((MODEL*)mem)->normals; + size = ((MODEL*)src)->normals; else - size = ((MODEL*)mem)->poly_block; + size = ((MODEL*)src)->poly_block; // if loaded externally don't copy from source lump - memcpy((u_char*)*dest, (u_char*)mem, size); + memcpy((u_char*)*dest, (u_char*)src, size); if (KeepNormals == 0) size = model->normals; @@ -317,7 +382,7 @@ MODEL* GetCarModel(char *src, char **dest, int KeepNormals, int modelNumber, int model->vertices += (int)model; model->normals += (int)model; - model->poly_block = (int)mem + model->poly_block; + model->poly_block = (int)src + model->poly_block; if (KeepNormals == 0) model->point_normals = 0; diff --git a/src_rebuild/Game/C/models.h b/src_rebuild/Game/C/models.h index 452f83923..fdda47a79 100644 --- a/src_rebuild/Game/C/models.h +++ b/src_rebuild/Game/C/models.h @@ -15,6 +15,7 @@ extern char *car_models_lump; extern MODEL* modelpointers[MAX_MODEL_SLOTS]; extern MODEL* pLodModels[MAX_MODEL_SLOTS]; +extern int litSprites[48]; extern unsigned short *Low2HighDetailTable; extern unsigned short *Low2LowerDetailTable; @@ -22,12 +23,13 @@ extern unsigned short *Low2LowerDetailTable; extern int num_models_in_pack; extern int CleanSpooledModelSlots(); +extern void ProcessModel(int modelIdx); extern void ProcessMDSLump(char *lump_file, int lump_size); // 0x00064CFC extern int ProcessCarModelLump(char *lump_ptr, int lump_size); // 0x00064E6C -extern MODEL * GetCarModel(char *src, char **dest, int KeepNormals, int modelNumber, int type); // 0x00065134 +extern MODEL * GetCarModel(char *src, char **dest, int KeepNormals); // 0x00065134 extern MODEL * FindModelPtrWithName(char *name); // 0x0005D40C diff --git a/src_rebuild/Game/C/motion_c.c b/src_rebuild/Game/C/motion_c.c index d76ec7586..c94bec7c4 100644 --- a/src_rebuild/Game/C/motion_c.c +++ b/src_rebuild/Game/C/motion_c.c @@ -16,7 +16,7 @@ #include "cars.h" #include "convert.h" -#ifdef USE_PGXP +#if USE_PGXP #include #endif @@ -524,7 +524,7 @@ void DrawBodySprite(LPPEDESTRIAN pDrawingPed, int boneId, VERTTYPE v1[2], VERTTY int pal; int cs, sn; - bone = (LIMBS)(boneId & 0x7f); + bone = (LIMBS)(boneId & 127); body_texture = MainPed[bone].ptd; if (bDoingShadow) @@ -607,12 +607,13 @@ void DrawBodySprite(LPPEDESTRIAN pDrawingPed, int boneId, VERTTYPE v1[2], VERTTY prims->x3 = v2[0] - FIXEDH(cs) - dx1; prims->y3 = v2[1] - FIXEDH(sn) - dy1; -#ifdef USE_PGXP +#if USE_PGXP if (!bDoingShadow) // [A] Psy-X is currently incorrectly offsets the offscreen PGXP geometry. We don't need it anyway. { + ushort pgxpIdx = PGXP_GetIndex(0) - 64; PGXPVData vdata1, vdata2; - PGXP_GetCacheData(&vdata1, PGXP_LOOKUP_VALUE(v1[0], v1[1]), 0); - PGXP_GetCacheData(&vdata2, PGXP_LOOKUP_VALUE(v2[0], v2[1]), 0); + PGXP_GetCacheData(&vdata1, PGXP_LOOKUP_VALUE(v1[0], v1[1]), pgxpIdx); + PGXP_GetCacheData(&vdata2, PGXP_LOOKUP_VALUE(v2[0], v2[1]), pgxpIdx); { float len; @@ -897,6 +898,13 @@ void SetupTannerSkeleton(LPPEDESTRIAN pDrawingPed) char* pC; SVECTOR* store; SVECTOR_NOPAD* pSVNP; +#ifdef PSX + store = (SVECTOR*)((u_char*)getScratchAddr(0) + 0x200); + static_assert(sizeof(SVECTOR) + NUM_BONES < 1024 - sizeof(_pct), "scratchpad overflow"); +#else + SVECTOR scratchVectors[64]; + store = scratchVectors; +#endif Skel[ROOT].pvOrigPos = (SVECTOR_NOPAD*)(pDrawingPed->motion + pDrawingPed->frame1 * 144 + 146); Skel[ROOT].pvRotation = (SVECTOR*)(pDrawingPed->motion + pDrawingPed->frame1 * 144 + 152); @@ -922,13 +930,6 @@ void SetupTannerSkeleton(LPPEDESTRIAN pDrawingPed) pC += sizeof(SVECTOR_NOPAD); } -#ifdef PSX - store = (SVECTOR*)((u_char*)getScratchAddr(0) + 0x200); -#else - SVECTOR scratchVectors[64]; - store = scratchVectors; -#endif - store[LOWERBACK].vx = Skel[LOWERBACK].pvOrigPos->vx; store[LOWERBACK].vy = -Skel[LOWERBACK].pvOrigPos->vy; store[LOWERBACK].vz = -Skel[LOWERBACK].pvOrigPos->vz; @@ -1003,25 +1004,26 @@ void SetupTannerSkeleton(LPPEDESTRIAN pDrawingPed) } // [A] - was inlined in newShowTanner -void DrawSprite(LPPEDESTRIAN pDrawingPed, BONE* pBone, VECTOR* vJPos) +void DrawSprite(LPPEDESTRIAN pDrawingPed, BONE* pBone, SVECTOR* vJPos) { VERTTYPE t0[2], t1[2]; // [A] was two longs int z, z1, z2; #ifdef PSX SVECTOR* data = (SVECTOR*)((u_char*)getScratchAddr(0) + 0x200); + static_assert(sizeof(SVECTOR) + NUM_BONES < 1024 - sizeof(_pct), "scratchpad overflow"); #else SVECTOR scratchVectors[64]; SVECTOR* data = scratchVectors; #endif - data[0].vx = vJPos[pBone->id & 0x7f].vx + pDrawingPed->position.vx - camera_position.vx; - data[0].vy = vJPos[pBone->id & 0x7f].vy + pDrawingPed->position.vy - camera_position.vy; - data[0].vz = vJPos[pBone->id & 0x7f].vz + pDrawingPed->position.vz - camera_position.vz; + data[0].vx = vJPos[pBone->id & 127].vx + pDrawingPed->position.vx - camera_position.vx; + data[0].vy = vJPos[pBone->id & 127].vy + pDrawingPed->position.vy - camera_position.vy; + data[0].vz = vJPos[pBone->id & 127].vz + pDrawingPed->position.vz - camera_position.vz; - data[1].vx = vJPos[pBone->pParent->id & 0x7f].vx + pDrawingPed->position.vx - camera_position.vx; - data[1].vy = vJPos[pBone->pParent->id & 0x7f].vy + pDrawingPed->position.vy - camera_position.vy; - data[1].vz = vJPos[pBone->pParent->id & 0x7f].vz + pDrawingPed->position.vz - camera_position.vz; + data[1].vx = vJPos[pBone->pParent->id & 127].vx + pDrawingPed->position.vx - camera_position.vx; + data[1].vy = vJPos[pBone->pParent->id & 127].vy + pDrawingPed->position.vy - camera_position.vy; + data[1].vz = vJPos[pBone->pParent->id & 127].vz + pDrawingPed->position.vz - camera_position.vz; gte_ldv0(&data[0]); gte_ldv1(&data[1]); @@ -1046,14 +1048,18 @@ void newShowTanner(LPPEDESTRIAN pDrawingPed) int draw; #ifdef PSX - VECTOR* spad = (VECTOR*)((u_char*)getScratchAddr(0) + 0x100); + VECTOR* playerPos = (VECTOR*)((u_char*)getScratchAddr(0) + 0x100); + VECTOR* cameraPos = (VECTOR*)((u_char*)getScratchAddr(0) + 0x100 + sizeof(VECTOR)); + SVECTOR* vJPos = (SVECTOR*)((u_char*)getScratchAddr(0) + 0x100 + sizeof(VECTOR) * 2); + static_assert(sizeof(VECTOR) * 2 + sizeof(SVECTOR) * NUM_BONES < 0x100, "Scratchpad local overflow"); + static_assert(sizeof(VECTOR) * 2 + sizeof(SVECTOR) * NUM_BONES < 1024 - sizeof(_pct), "Scratchpad overflow"); #else VECTOR spad[64]; -#endif VECTOR* playerPos = &spad[0]; VECTOR* cameraPos = &spad[1]; - VECTOR* vJPos = &spad[2]; + SVECTOR* vJPos = (SVECTOR*)&spad[2]; +#endif playerPos->vx = pDrawingPed->position.vx; playerPos->vy = pDrawingPed->position.vy - 15; // [A] elevate Tanner model a little bit so his legs are not in the ground (when Z-buffer enabled) @@ -1091,7 +1097,7 @@ void newShowTanner(LPPEDESTRIAN pDrawingPed) BONE* pBone = &Skel[id]; - if (pBone->id < 0x7f) + if (pBone->id < 127) { int lval; @@ -1137,7 +1143,7 @@ void newShowTanner(LPPEDESTRIAN pDrawingPed) BONE* pBone; pBone = &Skel[i]; - id = pBone->id & 0x7f; + id = pBone->id & 127; if (bDoingShadow) { @@ -1178,15 +1184,15 @@ void newShowTanner(LPPEDESTRIAN pDrawingPed) CVECTOR yycv = { 250, 250, 0 }; VECTOR v0 = { - vJPos[pBone->id & 0x7f].vx, - -vJPos[pBone->id & 0x7f].vy, - vJPos[pBone->id & 0x7f].vz + vJPos[pBone->id & 127].vx, + -vJPos[pBone->id & 127].vy, + vJPos[pBone->id & 127].vz }; VECTOR v1 = { - vJPos[pBone->pParent->id & 0x7f].vx, - -vJPos[pBone->pParent->id & 0x7f].vy, - vJPos[pBone->pParent->id & 0x7f].vz + vJPos[pBone->pParent->id & 127].vx, + -vJPos[pBone->pParent->id & 127].vy, + vJPos[pBone->pParent->id & 127].vz }; VECTOR ofs = *(VECTOR*)&pDrawingPed->position; @@ -1205,7 +1211,7 @@ void newShowTanner(LPPEDESTRIAN pDrawingPed) { BONE* pBone = &Skel[i]; - int id = pBone->id & 0x7f; + int id = pBone->id & 127; if (id != LSHOULDER && id != RSHOULDER @@ -1232,13 +1238,13 @@ void newShowTanner(LPPEDESTRIAN pDrawingPed) { SVECTOR v1, v2; - v1.vx = vJPos[pBone->id & 0x7f].vx; - v1.vy = vJPos[pBone->id & 0x7f].vy; - v1.vz = vJPos[pBone->id & 0x7f].vz; + v1.vx = vJPos[pBone->id & 127].vx; + v1.vy = vJPos[pBone->id & 127].vy; + v1.vz = vJPos[pBone->id & 127].vz; - v2.vx = vJPos[pBone->pParent->id & 0x7f].vx; - v2.vy = vJPos[pBone->pParent->id & 0x7f].vy; - v2.vz = vJPos[pBone->pParent->id & 0x7f].vz; + v2.vx = vJPos[pBone->pParent->id & 127].vx; + v2.vy = vJPos[pBone->pParent->id & 127].vy; + v2.vz = vJPos[pBone->pParent->id & 127].vz; bAllreadyRotated = 1; DoCivHead(pDrawingPed, &v2, &v1); @@ -1249,7 +1255,7 @@ void newShowTanner(LPPEDESTRIAN pDrawingPed) // clear all id flags for (i = 0; i < NUM_BONES; i++) - Skel[i].id = (LIMBS)(Skel[i].id & 0x7f); + Skel[i].id = (LIMBS)(Skel[i].id & 127); } // [D] [T] @@ -1259,8 +1265,8 @@ SVECTOR* GetModelVertPtr(LPPEDESTRIAN pDrawingPed, int boneId, int modelType) if (pDrawingPed->pedType != OTHER_MODEL) { - if (cTannerVNumbers[boneId & 0x7f] != -1) - return vTannerList + cTannerVNumbers[boneId & 0x7f]; + if (cTannerVNumbers[boneId & 127] != -1) + return vTannerList + cTannerVNumbers[boneId & 127]; return NULL; } @@ -1286,7 +1292,7 @@ SVECTOR* GetModelVertPtr(LPPEDESTRIAN pDrawingPed, int boneId, int modelType) startVertex = cJerichoVNumbers[5]; break; default: - return vTannerList + cTannerVNumbers[boneId & 0x7f]; + return vTannerList + cTannerVNumbers[boneId & 127]; } return vJerichoList + startVertex; @@ -1364,7 +1370,7 @@ void newRotateBones(LPPEDESTRIAN pDrawingPed, BONE* poBone) _sMatrix.t[1] = _svBone[0].vy; _sMatrix.t[2] = _svBone[0].vz; - _pMatrix = mStore[pBone->pParent->id & 0x7f]; + _pMatrix = mStore[pBone->pParent->id & 127]; gte_MulMatrix0(&_pMatrix, &_sMatrix, &_oMatrix); gte_SetRotMatrix(&_oMatrix); @@ -1378,7 +1384,7 @@ void newRotateBones(LPPEDESTRIAN pDrawingPed, BONE* poBone) pBone->vCurrPos.vy = _vBoneRotated.vy; pBone->vCurrPos.vz = _vBoneRotated.vz; - if (pBone->id < 0x7f) + if (pBone->id < 127) { pVerts = GetModelVertPtr(pDrawingPed, pBone->id, 0); @@ -1645,7 +1651,7 @@ void DrawTanner(LPPEDESTRIAN pPed) if (pPed->padId == 0) { - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { cV.b = 12; cV.g = 12; @@ -1693,7 +1699,7 @@ int DrawCharacter(LPPEDESTRIAN pPed) bDoingShadow = 1; v.vy = -camera_position.vy - MapHeight((VECTOR*)&pPed->position); - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { cV.b = cV.g = cV.r = 12; TannerShadow(pPed, &v, moon_position + GameLevel, &cV, pPed->dir.vy); @@ -1747,7 +1753,7 @@ void InitTannerShadow(void) POLY_FT4* poly; int i; - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) brightness = 12; else brightness = 32; @@ -2002,7 +2008,7 @@ void DoCivHead(LPPEDESTRIAN pPed, SVECTOR* vert1, SVECTOR* vert2) if (pPed->pallet & 0xf) { flags |= PLOT_CUSTOM_PALETTE; // set custom palette flag - plotContext.clut = civ_clut[0][texturePedHead.texture_number][pPed->pallet & 0xf] << 0x10; + plotContext.clut = civ_clut[0][texturePedHead.texture_number][pPed->pallet & 15]; } oldcombointensity = combointensity; diff --git a/src_rebuild/Game/C/objanim.c b/src_rebuild/Game/C/objanim.c index 89f11962b..039363c44 100644 --- a/src_rebuild/Game/C/objanim.c +++ b/src_rebuild/Game/C/objanim.c @@ -14,6 +14,7 @@ #include "spool.h" #include "system.h" #include "pause.h" +#include "draw.h" struct ANIMATED_OBJECT { @@ -78,7 +79,7 @@ CYCLE_OBJECT* Lev_CycleObjPtrs[] = { Lev3 }; -int Num_LevCycleObjs[] = { 2, 0, 12, 0 }; +int Num_LevCycleObjs[] = { numberOf(Lev0), 0, numberOf(Lev2), 0 }; ANIMATED_OBJECT Lev0AnimObjects[9] = { @@ -175,7 +176,6 @@ SMASHABLE_OBJECT smashable[] = { 0, 0, 0, 0, 0 } }; - int num_anim_objects = 0; int num_cycle_obj = 0; @@ -191,7 +191,7 @@ void InitCyclingPals(void) int i; // only enabled at Night - if (gTimeOfDay != 3) + if (gTimeOfDay != TIME_NIGHT) { num_cycle_obj = 0; return; @@ -220,7 +220,9 @@ void ColourCycle(void) RECT16 vram; if (!num_cycle_obj) + { return; + } if (LoadingArea != 0) { @@ -228,66 +230,76 @@ void ColourCycle(void) return; } + if (FrameCnt & 1) // [A] + { + return; + } + vram.w = 16; vram.h = 1; cyc = Lev_CycleObjPtrs[GameLevel]; - for (i = 0; i < num_cycle_obj; i++) + for (i = 0; i < num_cycle_obj; i++, cyc++) { + TEXTURE_DETAILS* cycTex = &cycle_tex[i]; bufaddr = (u_short*)cyclecluts[i].p; - if (tpageloaded[cycle_tex[i].texture_page] != 0) + if (tpageloaded[cycTex->texture_page] == 0) { - if (cycle_phase == 0) - { - // initialize - temp = texture_cluts[cycle_tex[i].texture_page][cycle_tex[i].texture_number]; + continue; + } - cyc->vx = vram.x = (temp & 0x3f) << 4; - cyc->vy = vram.y = (temp >> 6); + if (cycle_phase == 0) + { + // initialize clut data from VRAM + temp = texture_cluts[cycTex->texture_page][cycTex->texture_number]; - StoreImage(&vram, (u_long*)bufaddr); - } - else + cyc->vx = vram.x = (temp & 63) << 4; + cyc->vy = vram.y = (temp >> 6); + + StoreImage(&vram, (u_long*)bufaddr); + } + else + { + if ((cycle_timer & cyc->speed1) == 0) { - if ((cycle_timer & cyc->speed1) == 0) + if (cyc->start1 != -1) { - if (cyc->start1 != -1) - { - temp = bufaddr[cyc->start1]; - memmove((u_char*)(bufaddr + cyc->start1), (u_char*)(bufaddr + cyc->start1 + 1), (cyc->stop1 - cyc->start1) << 1); + temp = bufaddr[cyc->start1]; + memmove((u_char*)(bufaddr + cyc->start1), (u_char*)(bufaddr + cyc->start1 + 1), (cyc->stop1 - cyc->start1) * sizeof(ushort)); - bufaddr[cyc->stop1] = temp; - } + bufaddr[cyc->stop1] = temp; } + } - if ((cycle_timer & cyc->speed2) == 0) + if ((cycle_timer & cyc->speed2) == 0) + { + if (cyc->start2 != -1) { - if (cyc->start2 != -1) - { - temp = bufaddr[cyc->start2]; - memmove((u_char*)(bufaddr + cyc->start2), (u_char*)(bufaddr + cyc->start2 + 1), (cyc->stop2 - cyc->start2) << 1); + temp = bufaddr[cyc->start2]; + memmove((u_char*)(bufaddr + cyc->start2), (u_char*)(bufaddr + cyc->start2 + 1), (cyc->stop2 - cyc->start2) * sizeof(ushort)); - bufaddr[cyc->stop2] = temp; - } + bufaddr[cyc->stop2] = temp; } + } - vram.x = cyc->vx; - vram.y = cyc->vy; + vram.x = cyc->vx; + vram.y = cyc->vy; - SetDrawLoad(&cyclecluts[i], &vram); + SetDrawLoad(&cyclecluts[i], &vram); - addPrim(current->ot, &cyclecluts[i]); - } + addPrim(current->ot, &cyclecluts[i]); } - - cyc++; } if (cycle_phase != 0) + { cycle_timer++; - - cycle_phase ^= 1; + } + else + { + cycle_phase = 1; + } } @@ -319,20 +331,26 @@ void InitAnimatingObjects(void) { // My way int model_idx = FindModelIdxWithName(aop->name); + aop->model_num = model_idx; if (model_idx != -1 && modelpointers[model_idx] != &dummyModel) { modelPtr = modelpointers[model_idx]; modelPtr->flags2 |= MODEL_FLAG_ANIMOBJ; +#ifdef DYNAMIC_LIGHTING + if (gEnableDlights) + { + modelPtr->bounding_sphere <<= 3; + } +#endif // DYNAMIC_LIGHTING + if (aop->LitPoly) modelPtr->flags2 |= MODEL_FLAG_LAMP; - - aop->model_num = model_idx; // [A] store animated object number in normals pointer // after all it was always unused - modelPtr->normals = loop; + modelPtr->tri_verts = loop; if (modelPtr->instance_number != -1 && modelpointers[modelPtr->instance_number] != &dummyModel) @@ -340,16 +358,21 @@ void InitAnimatingObjects(void) modelPtr = modelpointers[modelPtr->instance_number]; modelPtr->flags2 |= MODEL_FLAG_ANIMOBJ; +#ifdef DYNAMIC_LIGHTING + if (gEnableDlights) + { + modelPtr->bounding_sphere <<= 3; + } +#endif // DYNAMIC_LIGHTING + if (aop->LitPoly) modelPtr->flags2 |= MODEL_FLAG_LAMP; // [A] store animated object number in normals pointer // after all it was always unused - modelPtr->normals = loop; + modelPtr->tri_verts = loop; } } - else - aop->model_num = -1; aop++; } @@ -380,9 +403,16 @@ void InitSpooledAnimObj(int model_number) if (aop->LitPoly) modelPtr->flags2 |= MODEL_FLAG_LAMP; +#ifdef DYNAMIC_LIGHTING + if (gEnableDlights) + { + modelPtr->bounding_sphere <<= 3; + } +#endif // DYNAMIC_LIGHTING + // [A] store animated object number in normals pointer // after all it was always unused - modelPtr->normals = i; + modelPtr->tri_verts = i; break; } @@ -416,10 +446,11 @@ void DrawAllAnimatingObjects(CELL_OBJECT** objects, int num_animated) model = modelpointers[type]; // [A] optimized - animate_object(cop, aop[model->normals].internal_id); + animate_object(cop, aop[model->tri_verts & 31].internal_id); } } + // [D] [T] void animate_object(CELL_OBJECT* cop, int type) { @@ -428,12 +459,11 @@ void animate_object(CELL_OBJECT* cop, int type) yang = cop->yang * 64; - // [A] Rev 1.1 has less of those types - if (GameLevel == 0) { switch (type) { + case 0: case 7: yang += 1024; @@ -441,15 +471,15 @@ void animate_object(CELL_OBJECT* cop, int type) if (phase == 1) { - AddTrafficLight(cop, 0, -0x2c4, -0x2d, 0x200, yang); + AddTrafficLight(cop, 0, -708, -45, 0x200, yang); } else if (phase == 2) { - AddTrafficLight(cop, 0, -0x284, -0x2d, 0x400, yang); + AddTrafficLight(cop, 0, -644, -45, 0x400, yang); } else if (phase == 3) { - AddTrafficLight(cop, 0, -0x244, -0x2d, 0x800, yang); + AddTrafficLight(cop, 0, -580, -45, 0x800, yang); } break; case 1: @@ -458,15 +488,15 @@ void animate_object(CELL_OBJECT* cop, int type) if (phase == 1) { - AddTrafficLight(cop, 0x196, -0x2c4, -0x2e, 0x200, yang); + AddTrafficLight(cop, 406, -708, -46, 0x200, yang); } else if (phase == 2) { - AddTrafficLight(cop, 0x196, -0x292, -0x2e, 0x400, yang); + AddTrafficLight(cop, 406, -658, -46, 0x400, yang); } else if (phase == 3) { - AddTrafficLight(cop, 0x196, -0x252, -0x2e, 0x800, yang); + AddTrafficLight(cop, 406, -594, -46, 0x800, yang); } break; case 2: @@ -474,27 +504,27 @@ void animate_object(CELL_OBJECT* cop, int type) if (gLightsOn == 0) break; - AddLightEffect(cop, 0x1ad, -0x4d2, 0, 0, 3); + AddLightEffect(cop, 429, -1234, 0, 0, 3); break; case 4: if (gLightsOn == 0) break; - AddLightEffect(cop, -0x1b0, -0x4d9, 0, 0, 3); - AddLightEffect(cop, 0x1b0, -0x4d9, 0, 0, 3); + AddLightEffect(cop, -432, -1241, 0, 0, 3); + AddLightEffect(cop, 432, -1241, 0, 0, 3); break; case 5: if (gLightsOn == 0) break; - AddLightEffect(cop, 0, -0x50, 0, 2, 2); + AddLightEffect(cop, 0, -80, 0, 2, 2); break; case 6: if (gLightsOn == 0) break; - AddLightEffect(cop, 0xea, -0x47a, 0, 0, 3); - AddLightEffect(cop, -0xea, -0x47a, 0, 0, 3); + AddLightEffect(cop, 234, -1146, 0, 0, 3); + AddLightEffect(cop, -234, -1146, 0, 0, 3); } } else if (GameLevel == 1) @@ -506,15 +536,15 @@ void animate_object(CELL_OBJECT* cop, int type) if (phase == 2) { - AddTrafficLight(cop, -0x1a1, -800, -0x1e, 0x400, yang); + AddTrafficLight(cop, -417, -800, -30, 0x400, yang); } else if (phase == 1) { - AddTrafficLight(cop, -0x1ea, -800, -0x1e, 0x200, yang); + AddTrafficLight(cop, -490, -800, -30, 0x200, yang); } else if (phase == 3) { - AddTrafficLight(cop, -0x157, -800, -0x1e, 0x800, yang); + AddTrafficLight(cop, -343, -800, -30, 0x800, yang); } break; @@ -522,20 +552,20 @@ void animate_object(CELL_OBJECT* cop, int type) if (gLightsOn == 0) break; - AddSmallStreetLight(cop, 0xe6, -0x442, 0, 0); + AddSmallStreetLight(cop, 230, -1090, 0, 0); break; case 3: if (gLightsOn == 0) break; - AddLightEffect(cop, -0x265, -0x7d2, 0, 0, 3); + AddLightEffect(cop, -613, -2002, 0, 0, 3); break; case 4: if (gLightsOn == 0) break; - AddLightEffect(cop, -0x250, -2000, 0, 0, 3); - AddLightEffect(cop, 0x252, -2000, 0, 0, 3); + AddLightEffect(cop, -592, -2000, 0, 0, 3); + AddLightEffect(cop, 594, -2000, 0, 0, 3); break; } } @@ -548,21 +578,21 @@ void animate_object(CELL_OBJECT* cop, int type) if (phase == 1) { - AddTrafficLight(cop, -0x857, -0x458, -0x44, 0x200, yang); - AddTrafficLight(cop, -0x520, -0x421, -0x44, 0x200, yang); - AddTrafficLight(cop, -0x202, -0x400, -0x44, 0x200, yang); + AddTrafficLight(cop, -2135, -1112, -68, 0x200, yang); + AddTrafficLight(cop, -1312, -1057, -68, 0x200, yang); + AddTrafficLight(cop, -514, -1024, -68, 0x200, yang); } else if (phase == 2) { - AddTrafficLight(cop, -0x85c, -0x3fd, -0x41, 0x400, yang); - AddTrafficLight(cop, -0x51e, -0x3d4, -0x41, 0x400, yang); - AddTrafficLight(cop, -0x208, -0x3ab, -0x41, 0x400, yang); + AddTrafficLight(cop, -2140, -1021, -65, 0x400, yang); + AddTrafficLight(cop, -1310, -980, -65, 0x400, yang); + AddTrafficLight(cop, -520, -939, -65, 0x400, yang); } else if (phase == 3) { - AddTrafficLight(cop, -0x85a, -0x3a9, -0x3e, 0x800, yang); - AddTrafficLight(cop, -0x51d, -0x381, -0x3e, 0x800, yang); - AddTrafficLight(cop, -0x206, -0x353, -0x3e, 0x800, yang); + AddTrafficLight(cop, -2138, -937, -62, 0x800, yang); + AddTrafficLight(cop, -1309, -897, -62, 0x800, yang); + AddTrafficLight(cop, -518, -851, -62, 0x800, yang); } break; case 1: @@ -570,41 +600,42 @@ void animate_object(CELL_OBJECT* cop, int type) if (phase == 1) { - AddTrafficLight(cop, -4, -0x219, -0x29, 0x200, yang); + AddTrafficLight(cop, -4, -537, -41, 0x200, yang); } else if (phase == 2) { - AddTrafficLight(cop, -4, -0x1d2, -0x29, 0x400, yang); + AddTrafficLight(cop, -4, -466, -41, 0x400, yang); } else if (phase == 3) { - AddTrafficLight(cop, -4, -0x18b, -0x29, 0x800, yang); + AddTrafficLight(cop, -4, -395, -41, 0x800, yang); } break; case 2: if (gLightsOn == 0) break; - AddLightEffect(cop, -0x348, -0x7b4, -0x3d, 0, 3); + AddLightEffect(cop, -840, -1972, -61, 0, 3); break; case 3: if (gLightsOn == 0) break; - AddLightEffect(cop, -0x361, -0x8c9, 0, 0, 3); - AddLightEffect(cop, 0x361, -0x8c9, 0, 0, 3); + AddLightEffect(cop, -865, -2249, 0, 0, 3); + AddLightEffect(cop, 865, -2249, 0, 0, 3); break; case 4: if (gLightsOn == 0) break; + // spooled? if (cop->pos.vx - 137190U < 50687 && cop->pos.vz > 713372 && cop->pos.vz < 719516) { - AddSmallStreetLight(cop, -0x26c, -0x65, 0, 0); + AddSmallStreetLight(cop, -620, -101, 0, 0); break; } - AddLightEffect(cop, -0x26c, -0x652, 0, 0, 3); + AddLightEffect(cop, -620, -1618, 0, 0, 3); break; } } @@ -617,15 +648,15 @@ void animate_object(CELL_OBJECT* cop, int type) if (phase == 1) { - AddTrafficLight(cop, -0x2cf, -0x38a, -0x16, 0x200, yang); + AddTrafficLight(cop, -719, -906, -22, 0x200, yang); } else if (phase == 2) { - AddTrafficLight(cop, -0x2cf, -0x345, -0x16, 0x400, yang); + AddTrafficLight(cop, -719, -837, -22, 0x400, yang); } else if (phase == 3) { - AddTrafficLight(cop, -0x2cf, -0x2fa, -0x16, 0x800, yang); + AddTrafficLight(cop, -719, -762, -22, 0x800, yang); } break; case 1: @@ -633,36 +664,36 @@ void animate_object(CELL_OBJECT* cop, int type) if (phase == 1) { - AddTrafficLight(cop, 0, -0x28e, -0x15, 0x200, yang); + AddTrafficLight(cop, 0, -654, -21, 0x200, yang); } else if (phase == 2) { - AddTrafficLight(cop, 0, -0x242, -0x15, 0x400, yang); + AddTrafficLight(cop, 0, -578, -21, 0x400, yang); } else if (phase == 3) { - AddTrafficLight(cop, 0, -0x1fd, -0x15, 0x800, yang); + AddTrafficLight(cop, 0, -509, -21, 0x800, yang); } break; case 2: if (gLightsOn == 0) break; - AddLightEffect(cop, -0x1f1, -0x59d, 0, 0, 3); + AddLightEffect(cop, -497, -1437, 0, 0, 3); break; case 3: if (gLightsOn == 0) break; - AddLightEffect(cop, 0, -0xaa7, 0, 0, 3); + AddLightEffect(cop, 0, -2727, 0, 0, 3); break; case 4: if (gLightsOn == 0) break; - AddSmallStreetLight(cop, 0, -0x492, 0, 1); + AddSmallStreetLight(cop, 0, -1170, 0, 1); break; } } diff --git a/src_rebuild/Game/C/objcoll.c b/src_rebuild/Game/C/objcoll.c index f20ed8188..a74cfcb9d 100644 --- a/src_rebuild/Game/C/objcoll.c +++ b/src_rebuild/Game/C/objcoll.c @@ -41,15 +41,12 @@ char CellEmpty(VECTOR *pPosition, int radius) cell_x = (pPosition->vx + units_across_halved) / MAP_CELL_SIZE; cell_z = (pPosition->vz + units_down_halved) / MAP_CELL_SIZE; - ppco = GetFirstPackedCop(cell_x, cell_z, &ci, 0); - - while(ppco) + for (ppco = GetFirstPackedCop(cell_x, cell_z, &ci, 0); ppco; ppco = GetNextPackedCop(&ci)) { type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10); pModel = modelpointers[type]; - if ((uint)pModel->collision_block > 0 && - (pModel->flags2 & (MODEL_FLAG_CHAIR | MODEL_FLAG_SMASHABLE)) == 0) + if ((uint)pModel->collision_block > 0 && (pModel->flags2 & (MODEL_FLAG_CHAIR | MODEL_FLAG_SMASHABLE)) == 0) { QuickUnpackCellObject(ppco, &ci.nearCell, &tempCO); @@ -87,7 +84,7 @@ char CellEmpty(VECTOR *pPosition, int radius) int theta; MATRIX2* mat; - yang = -tempCO.yang & 0x3f; + yang = -tempCO.yang & 63; theta = (tempCO.yang + collide->yang) * 64; mat = &matrixtable[yang]; @@ -198,8 +195,6 @@ char CellEmpty(VECTOR *pPosition, int radius) } } } - - ppco = GetNextPackedCop(&ci); } return 1; @@ -238,22 +233,34 @@ char CellAtPositionEmpty(VECTOR *pPosition, int radius) } +struct tRay +{ + LONGVECTOR4 org, dir; +}; + +struct tRange +{ + int lower, upper; +}; + +struct tAABB +{ + tRange slab[3]; +}; + + // [D] [T] int RaySlabsIntersection(tRay *ray, tAABB *bbox) { - int dir; - int d; - int i; + int dir, d, i; - tRange inside; - tRange cabbage; - tRange scaledCabbage; + tRange inside, cabbage, scaledCabbage; inside.lower = 0; inside.upper = 4096; - i = 0; - do { + for (i = 0; i < 3; i++) + { d = -1; cabbage.lower = bbox->slab[i].lower - ray->org[i]; @@ -294,10 +301,7 @@ int RaySlabsIntersection(tRay *ray, tAABB *bbox) if (inside.upper < inside.lower) return 0; - - i++; - - } while(i < 3); + } return 1; } @@ -310,31 +314,20 @@ char lineClear(VECTOR *v1, VECTOR *v2) PACKED_CELL_OBJECT* ppco; CELL_OBJECT tempCO; MATRIX2* mat; - int cell_z; - int cell_x; - int yang; + int cell_x, cell_z; + int yang, theta; MODEL* pModel; - int theta; - int dx,dz; - - int cs; - int sn; - + int cs, sn; COLLISION_PACKET* collide; - VECTOR pos; - VECTOR va; - VECTOR vb; + VECTOR pos, va, vb; tRay ray; tAABB box; int we; - int ocz; - int ocx; - int box_loop; // $s5 - int num_cb; // $s6 - int sphere_sq; // $v0 - int xd; // $a0 - int zd; // $v1 + int ocx, ocz; + int box_loop, num_cb; + int sphere_sq; + int xd, zd; #if 0 //def PSX CELL_ITERATOR& ci = *(CELL_ITERATOR*)((u_char*)getScratchAddr(0) + 1024 - sizeof(CELL_ITERATOR)); @@ -356,9 +349,8 @@ char lineClear(VECTOR *v1, VECTOR *v2) ocx = -1; ocz = -1; - we = 0; - - do { + for (we = 0; we < 2; we++) + { if (we == 0) { cell_x = (v2->vx + units_across_halved) / MAP_CELL_SIZE; @@ -370,17 +362,15 @@ char lineClear(VECTOR *v1, VECTOR *v2) cell_z = (v1->vz + units_down_halved) / MAP_CELL_SIZE; } - if ((ocx != cell_x) || (ocz != cell_z)) + if (ocx != cell_x || ocz != cell_z) { - ppco = GetFirstPackedCop(cell_x, cell_z, &ci, 0); - - while (ppco) + for (ppco = GetFirstPackedCop(cell_x, cell_z, &ci, 0); ppco; ppco = GetNextPackedCop(&ci)) { QuickUnpackCellObject(ppco, &ci.nearCell, &tempCO); pModel = modelpointers[tempCO.type]; - xd = ((tempCO.pos.vx - ((va.vx + vb.vx) / 2 & 0xffffU)) * 0x10000) >> 0x10; - zd = ((tempCO.pos.vz - ((va.vz + vb.vz) / 2 & 0xffffU)) * 0x10000) >> 0x10; + xd = tempCO.pos.vx - (short)((va.vx + vb.vx) / 2); + zd = tempCO.pos.vz - (short)((va.vz + vb.vz) / 2); sphere_sq = pModel->bounding_sphere + 800; @@ -406,13 +396,13 @@ char lineClear(VECTOR *v1, VECTOR *v2) dx = va.vx - (tempCO.pos.vx + FIXEDH(collide->xpos * mat->m[0][0] + collide->zpos * mat->m[2][0])); dz = va.vz - (tempCO.pos.vz + FIXEDH(collide->xpos * mat->m[0][2] + collide->zpos * mat->m[2][2])); - box.slab[0].upper = collide->xsize / 2 +testRadius; + box.slab[0].upper = collide->xsize / 2 + testRadius; box.slab[0].lower = -box.slab[0].upper; - - box.slab[1].upper = collide->ysize / 2 +testRadius; + + box.slab[1].upper = collide->ysize / 2 + testRadius; box.slab[1].lower = -box.slab[1].upper; - - box.slab[2].upper = collide->zsize / 2 +testRadius; + + box.slab[2].upper = collide->zsize / 2 + testRadius; box.slab[2].lower = -box.slab[2].upper; ray.org[0] = FIXEDH(cs * dx - sn * dz); @@ -503,15 +493,12 @@ char lineClear(VECTOR *v1, VECTOR *v2) collide++; } } - ppco = GetNextPackedCop(&ci); } } - we++; - ocx = cell_x; ocz = cell_z; - } while (we < 2); + } return 1; } @@ -555,9 +542,7 @@ void CollisionCopList(XZPAIR* pos, int* count) // check if we have valid region if (cbr.x + cbr.z * regions_across == RoadMapRegions[(cbr.x & 1) + (cbr.z & 1) * 2]) { - ppco = GetFirstPackedCop(cell.x, cell.z, &ci, 1, cellLevel); - - while (ppco) + for (ppco = GetFirstPackedCop(cell.x, cell.z, &ci, 1, cellLevel); ppco; ppco = GetNextPackedCop(&ci)) { type = (ppco->value >> 6) | ((ppco->pos.vy & 1) << 10); @@ -576,8 +561,6 @@ void CollisionCopList(XZPAIR* pos, int* count) pcoplist[cnt] = ppco; cnt++; } - - ppco = GetNextPackedCop(&ci); } } @@ -623,7 +606,6 @@ void CheckScenaryCollisions(CAR_DATA *cp) { int count; int num_cb; - int coll_test_count; int yang; int minDist; COLLISION_PACKET *collide; @@ -660,7 +642,6 @@ void CheckScenaryCollisions(CAR_DATA *cp) else extraDist = 580; - // [A] FIXME: replace with 'cell_header.cell_size' cell.x = (player_pos.vx + units_across_halved - (MAP_REGION_SIZE*MAP_REGION_SIZE)) / MAP_CELL_SIZE; cell.z = (player_pos.vz + units_down_halved - (MAP_REGION_SIZE*MAP_REGION_SIZE)) / MAP_CELL_SIZE; @@ -678,14 +659,19 @@ void CheckScenaryCollisions(CAR_DATA *cp) cop = &EventCop[count - mdcount]; model = modelpointers[cop->type]; - num_cb = *(int*)model->collision_block; // box count if ((uint)model->collision_block > 0 /*&& model->num_vertices - 3 < 300 && model->num_point_normals < 300 && - model->num_polys < 300*/ && - num_cb > 0) + model->num_polys < 300*/) { + num_cb = *(int*)model->collision_block; // box count + + if (!num_cb) + { + continue; + } + dx = cop->pos.vx - player_pos.vx; dz = cop->pos.vz - player_pos.vz; @@ -700,7 +686,6 @@ void CheckScenaryCollisions(CAR_DATA *cp) yang = -cop->yang & 63; // box 'rotated' by matrix - // [A] FIXME: replace add+shift by division bbox.pos.vx = cop->pos.vx + FIXEDH(collide->xpos * matrixtable[yang].m[0][0] + collide->zpos * matrixtable[yang].m[2][0]); bbox.pos.vy = cop->pos.vy + collide->ypos; bbox.pos.vz = cop->pos.vz + FIXEDH(collide->xpos * matrixtable[yang].m[0][2] + collide->zpos * matrixtable[yang].m[2][2]); @@ -741,11 +726,12 @@ void CheckScenaryCollisions(CAR_DATA *cp) } else if (cp->controlType == CONTROL_TYPE_CAMERACOLLIDER) { - if ((model->flags2 & (MODEL_FLAG_CHAIR | MODEL_FLAG_SMASHABLE)) == 0 && - (bbox.xsize > 100 || (bbox.zsize > 100))) + if ((model->flags2 & (MODEL_FLAG_CHAIR | MODEL_FLAG_SMASHABLE)) == 0 && (bbox.xsize > 100 || bbox.zsize > 100)) { - coll_test_count = 5; - + int diff; + int coll_test_count = 2; // [A] only two tests needed + int prevDistance = gCameraDistance; + bbox.xsize += 100; bbox.zsize += 100; @@ -753,16 +739,15 @@ void CheckScenaryCollisions(CAR_DATA *cp) minDist = lbody / 2; - while (coll_test_count > 0 && minDist <= gCameraDistance && CarBuildingCollision(cp, &bbox, cop, 0)) + while (coll_test_count > 0 && gCameraDistance > minDist && CarBuildingCollision(cp, &bbox, cop, 0)) { - gCameraDistance -= gCameraBoxOverlap; - - if (gCameraDistance < minDist) - gCameraDistance = minDist; - - cp->hd.where.t[0] = car_data[0].hd.where.t[0] + FIXEDH((gCameraDistance * RSIN(cp->hd.direction)) / 2); - cp->hd.where.t[2] = car_data[0].hd.where.t[2] + FIXEDH((gCameraDistance * RCOS(cp->hd.direction)) / 2); - + gCameraDistance = MAX(minDist, gCameraDistance - gCameraBoxOverlap); + diff = prevDistance - gCameraDistance; + prevDistance = gCameraDistance; + + cp->hd.where.t[0] -= FIXEDH((diff * RSIN(cp->hd.direction)) / 2); + cp->hd.where.t[2] -= FIXEDH((diff * RCOS(cp->hd.direction)) / 2); + coll_test_count--; } } @@ -771,14 +756,18 @@ void CheckScenaryCollisions(CAR_DATA *cp) { if (count >= mdcount && cop->pad != 0) { + int extraFlags; + extraFlags = 0; cp->st.n.linearVelocity[2] = ExBoxDamage + cp->st.n.linearVelocity[2]; - - if (CarBuildingCollision(cp, &bbox, cop, (cop->pad == 1) ? CollisionCheckFlag_IsVegasMovingTrain : 0)) +#if ENABLE_GAME_FIXES + extraFlags |= (cop->pad == 1) ? CollisionCheckFlag_IsVegasMovingTrain : 0; +#endif + if (CarBuildingCollision(cp, &bbox, cop, extraFlags)) { cp->ap.needsDenting = 1; } - //cp->st.n.linearVelocity[2] -= 700000; // [A] Vegas train velocity - disabled here + //cp->st.n.linearVelocity[2] -= 700000; // [A] Vegas train velocity - disabled here, see flag above } else { @@ -888,8 +877,8 @@ int QuickBuildingCollisionCheck(VECTOR *pPos, int dir, int l, int w, int extra) cd[1].length[0] = collide->zsize / 2 + 100; cd[1].length[1] = collide->xsize / 2 + 100; - cd[1].x.vx = pPos->vx + (((offset.vx - pPos->vx) << 0x10) >> 0x10); - cd[1].x.vz = pPos->vz + (((offset.vz - pPos->vz) << 0x10) >> 0x10); + cd[1].x.vx = pPos->vx + (short)(offset.vx - pPos->vx); + cd[1].x.vz = pPos->vz + (short)(offset.vz - pPos->vz); cd[1].vel.vx = 0; cd[1].vel.vz = 0; diff --git a/src_rebuild/Game/C/overlay.c b/src_rebuild/Game/C/overlay.c index ea17f0439..3fbfd6cdd 100644 --- a/src_rebuild/Game/C/overlay.c +++ b/src_rebuild/Game/C/overlay.c @@ -123,19 +123,17 @@ void InitOverlays(void) } // [D] [T] -void SetFullscreenDrawing(void) +void SetFullscreenDrawing(int ofs) { DR_ENV *drenv; DRAWENV drawenv; - drenv = (DR_ENV *)current->primptr; - drawenv.clip.x = 256; SetDefDrawEnv(&drawenv, 0, current->draw.clip.y & 256, 320, 256); + drenv = (DR_ENV*)current->primptr; SetDrawEnv(drenv, &drawenv); - - addPrim(current->ot + 2, drenv); + addPrim(current->ot + ofs, drenv); current->primptr += sizeof(DR_ENV); } @@ -238,7 +236,7 @@ void DrawPercentageBar(PERCENTAGE_BAR *bar) poly->y2 = max_y; poly->y3 = max_y; - addPrim((u_long*)(current->ot + 1), poly); + addPrim(current->ot + 1, poly); current->primptr += sizeof(POLY_G4); } @@ -271,7 +269,7 @@ void DrawPercentageBar(PERCENTAGE_BAR *bar) poly2->y2 = max_y; poly2->y3 = max_y; - addPrim((u_long*)(current->ot+1), poly2); + addPrim(current->ot+1, poly2); current->primptr += sizeof(POLY_G4); // draw contours @@ -293,7 +291,7 @@ void DrawPercentageBar(PERCENTAGE_BAR *bar) lineF4->y2 = max_y; lineF4->y3 = max_y; - addPrim((u_long*)(current->ot + 1), lineF4); + addPrim(current->ot + 1, lineF4); current->primptr += sizeof(LINE_F4); LINE_F2* lineF2 = (LINE_F2*)current->primptr; @@ -308,7 +306,7 @@ void DrawPercentageBar(PERCENTAGE_BAR *bar) lineF2->x1 = min_x - 1; lineF2->y1 = max_y; - addPrim((u_long*)(current->ot + 1), lineF2); + addPrim(current->ot + 1, lineF2); current->primptr += sizeof(LINE_F2); TransparencyOn(current->ot + 1, 0x20); @@ -441,7 +439,7 @@ void DrawProximityBar(PERCENTAGE_BAR *bar) lineF4->y2 = max_y; lineF4->y3 = max_y; - addPrim((u_long*)(current->ot + 1), lineF4); + addPrim(current->ot + 1, lineF4); current->primptr += sizeof(LINE_F4); LINE_F2* lineF2 = (LINE_F2*)current->primptr; @@ -456,7 +454,7 @@ void DrawProximityBar(PERCENTAGE_BAR *bar) lineF2->x1 = min_x - 1; lineF2->y1 = max_y; - addPrim((u_long*)(current->ot + 1), lineF2); + addPrim(current->ot + 1, lineF2); current->primptr += sizeof(LINE_F2); TransparencyOn(current->ot + 1, 0x20); @@ -704,7 +702,7 @@ void DisplayOverlays(void) if (CurrentPlayerView == 0) return; - SetFullscreenDrawing(); + SetFullscreenDrawing(2); } UpdateFlashValue(); diff --git a/src_rebuild/Game/C/overlay.h b/src_rebuild/Game/C/overlay.h index 0163251a7..bddde693f 100644 --- a/src_rebuild/Game/C/overlay.h +++ b/src_rebuild/Game/C/overlay.h @@ -36,7 +36,7 @@ extern char OverlayFlashValue; extern void InitOverlays(); // 0x00014A58 extern void DisplayOverlays(); // 0x00014C3C -extern void SetFullscreenDrawing(); // 0x00015E70 +extern void SetFullscreenDrawing(int ofs); // 0x00015E70 extern void InitPercentageBar(PERCENTAGE_BAR *bar, int size, COLOUR_BAND *pColourBand, char *tag); // 0x00015F20 extern void EnablePercentageBar(PERCENTAGE_BAR *bar, int max); // 0x00015F58 diff --git a/src_rebuild/Game/C/overmap.c b/src_rebuild/Game/C/overmap.c index 16018e361..5c0de75ca 100644 --- a/src_rebuild/Game/C/overmap.c +++ b/src_rebuild/Game/C/overmap.c @@ -404,7 +404,7 @@ void ProcessOverlayLump(char *lump_ptr, int lump_size) D_MALLOC_END(); // load CLUT - LoadImage(&mapclutpos, (u_long *)(MapBitMaps + 512)); + LoadImage(&mapclutpos, (u_long*)(MapBitMaps + 512)); DrawSync(0); } @@ -425,14 +425,14 @@ void LoadMapTile(int tpage, int x, int y) temp = x * 32; if (idx > -1 && idx < overlaidmaps[GameLevel].toptile && - temp > -1 && (temp < overlaidmaps[GameLevel].width)) + temp > -1 && temp < overlaidmaps[GameLevel].width) { UnpackRNC(MapBitMaps + *((ushort*)MapBitMaps + idx), MapBuffer); } else { for (count = 0; count < 512; count++) - MapBuffer[count++] = overlaidmaps[GameLevel].dummy; + MapBuffer[count] = overlaidmaps[GameLevel].dummy; } #ifdef PSX @@ -527,7 +527,7 @@ void DrawN(VECTOR *pScreenPosition, int direct) linef2->x1 = lastPoint.x; linef2->y1 = lastPoint.y; - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { linef2->r0 = 75; linef2->g0 = 75; @@ -849,8 +849,7 @@ void DrawSightCone(COP_SIGHT_DATA *pCopSightData, VECTOR *pPosition, int directi // [D] [T] u_int Long2DDistance(VECTOR *pPoint1, VECTOR *pPoint2) { - int tempTheta; - int theta; + int theta, tempTheta; u_int result; VECTOR delta; @@ -859,7 +858,7 @@ u_int Long2DDistance(VECTOR *pPoint1, VECTOR *pPoint2) theta = ratan2(delta.vz, delta.vx); - if ((theta & 0x7ff) - 512U <= 1024) + if ((theta & 2047) - 512U <= 1024) { tempTheta = RSIN(theta); result = delta.vz; @@ -870,7 +869,7 @@ u_int Long2DDistance(VECTOR *pPoint1, VECTOR *pPoint2) result = delta.vx; } - if (result < 0x80000) + if (result < 512 * 1024) result = (result << 12) / tempTheta; else result = (result << 9) / tempTheta << 3; @@ -899,7 +898,7 @@ void InitMultiplayerMap(void) rect.w = 16; rect.h = 64; - LoadImage(&rect, (u_long *)MapBitMaps); + LoadImage(&rect, (u_long*)MapBitMaps); DrawSync(0); } @@ -1060,7 +1059,7 @@ void DrawMultiplayerMap(void) poly->clut = MapClut; poly->tpage = MapTPage; - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) r = 50; else r = 100; @@ -1174,12 +1173,7 @@ void DrawOverheadMap(void) } } - // for restoring - drarea = (DR_AREA *)current->primptr; - SetDrawArea(drarea, ¤t->draw.clip); - - addPrim(current->ot + 1, drarea); - current->primptr += sizeof(DR_AREA); + SetFullscreenDrawing(1); WorldToOverheadMapPositions((VECTOR *)player->pos, &vec, 1, 0, 0); @@ -1370,7 +1364,7 @@ void DrawOverheadMap(void) setPolyFT4(spt); setSemiTrans(spt, 1); - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) spt->r0 = spt->g0 = spt->b0 = 50; else spt->r0 = spt->g0 = spt->b0 = 100; @@ -1449,7 +1443,7 @@ void DrawOverheadMap(void) clipped_size.x = map_minX + 1; clipped_size.w = MAP_SIZE_W - 1; clipped_size.h = MAP_SIZE_H; - clipped_size.y = current->draw.clip.y + map_minY;// +1; + clipped_size.y = (current->draw.clip.y & 256) + map_minY; drarea = (DR_AREA*)current->primptr; @@ -1810,7 +1804,7 @@ void DrawFullscreenMap(void) SetTextColour(128, 128, 128); // print string with special characters representing some images inserted into it - sprintf(str, "\x80 %s \x81 %s \x8a %s", G_LTXT(GTXT_Exit), G_LTXT(GTXT_Rotation), G_LTXT(GTXT_Move)); + sprintf(str, "\x80 %s \x81 %s \x8a %s", G_LTXT(GTXT_Back), G_LTXT(GTXT_Rotation), G_LTXT(GTXT_Move)); PrintStringCentred(str, SCREEN_H - 30); // 226 } diff --git a/src_rebuild/Game/C/pathfind.c b/src_rebuild/Game/C/pathfind.c index 86409d876..7ee0a9225 100644 --- a/src_rebuild/Game/C/pathfind.c +++ b/src_rebuild/Game/C/pathfind.c @@ -10,6 +10,10 @@ #include "felony.h" #include "map.h" +#ifdef PSX +#pragma GCC optimization ("O3") +#endif + #define DEBUG_PATHFINDING_VIEW 0 #if DEBUG_PATHFINDING_VIEW && !defined(PSX) @@ -19,19 +23,17 @@ struct tNode { - int vx; - int vy; - int vz; + int vx, vy, vz; u_short dist; u_short ptoey; // just a padding. }; struct XZDIR { - short dx; - short dz; + short dx, dz; }; +// Fast Marching method ushort distanceCache[16384]; char omap[128][16]; // obstacle map 128x128 (bit field) int dunyet[32][2]; // scanned cell map (32x32, multi-level bitfield) @@ -146,7 +148,7 @@ void DebugDisplayObstacleMap() n.vx = player[0].pos[0]; n.vz = player[0].pos[2]; n.vy = pos_y; - n.vy = MapHeight((VECTOR*)&n); + //n.vy = MapHeight((VECTOR*)&n); for (int i = 0; i < 128; i++) { @@ -178,7 +180,7 @@ void DebugDisplayObstacleMap() n.vx = px << 8; n.vz = pz << 8; - n.vy = MapHeight((VECTOR*)&n); + n.vy = 0;// MapHeight((VECTOR*)&n); int dist = distanceCache[(n.vx >> 2 & 0x3f80U | n.vz >> 9 & 0x7fU) ^ (n.vy & 1U) * 0x2040 ^ (n.vy & 2U) << 0xc];// distanceCache[((pos_x+i & 127) * 128) + (j + pos_z & 127)]; @@ -268,9 +270,10 @@ void WunCell(VECTOR* pbase) int height1; int i, j; - // [A] hack with height map (fixes some bits in Havana) - height1 = MapHeight(pbase); - +#if ENABLE_GAME_FIXES + // start with the base (player) height + height1 = pbase->vy; + pbase->vx += 512; pbase->vz += 512; @@ -279,7 +282,9 @@ void WunCell(VECTOR* pbase) pbase->vx -= 512; pbase->vz -= 512; - if (height1 - v[0].vy > 100) + // if base height differs from map height too much (we are on bridge etc) + // we then use base height to ensure that obstacles are locally correct + if (ABS(height1 - v[0].vy) > 100) v[0].vy = height1; v[0].vy += 32; @@ -287,7 +292,6 @@ void WunCell(VECTOR* pbase) // [A] definitely better code // new 16 vs old 12 passes but map is not leaky at all - for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) @@ -298,6 +302,45 @@ void WunCell(VECTOR* pbase) OMapSet(v[0].vx >> 8, v[0].vz >> 8, CellAtPositionEmpty(&v[0], 128) == 0); } } +#else + pbase->vx = pbase->vx + 512; + pbase->vz = pbase->vz + 512; + + height1 = MapHeight(pbase); + + v[0].vy = height1 + 60; + + pbase->vx = pbase->vx - 512; + pbase->vz = pbase->vz - 512; + v[1].vy = v[0].vy; + + for (i = 0; i < 2; i++) + { + if (i != 0) + pbase->vx += 512; + + v[0].vx = pbase->vx; + v[0].vz = pbase->vz; + + for (j = 0; j < 6; j++) + { + int dx, dz; + v[0].vx = pbase->vx + ends[j][0].dx; + v[0].vz = pbase->vz + ends[j][0].dz; + + v[1].vx = pbase->vx + ends[j][1].dx; + v[1].vz = pbase->vz + ends[j][1].dz; + + dx = v[0].vx + v[1].vx >> 1; + dz = v[0].vz + v[1].vz >> 1; + + OMapSet(dx >> 8, dz >> 8, lineClear(&v[0], &v[1]) == 0); + } + + if (i != 0) + pbase->vx -= 512; + } +#endif } // [A] function that invalidates map at ends @@ -308,8 +351,8 @@ void InvalidateMapEnds() int tile; int i; XZPAIR pos; - pos.x = (player[0].pos[0] & 0xfffffc00) >> 10; - pos.z = (player[0].pos[2] & 0xfffffc00) >> 10; + pos.x = (player[0].pos[0] & ~1023) >> 10; + pos.z = (player[0].pos[2] & ~1023) >> 10; for(i = 0; i < 32; i++) { @@ -331,8 +374,7 @@ void InvalidateMapEnds() void InvalidateMap(void) { int dir; - int p; - int q; + int p, q; int count; int px, pz; VECTOR bPos; @@ -342,11 +384,10 @@ void InvalidateMap(void) p = 0; dir = 0; - bPos.vx = player[0].pos[0] & 0xfffffc00; - bPos.vz = player[0].pos[2] & 0xfffffc00; + bPos.vx = player[0].pos[0] & ~1023; + bPos.vz = player[0].pos[2] & ~1023; - count = 0; - do + for(count = 0; count < 1024; count++) { px = bPos.vx >> 10; pz = bPos.vz >> 10; @@ -358,39 +399,25 @@ void InvalidateMap(void) if (dir == 0) { - p++; bPos.vx += MAP_CELL_SIZE / 2; - - if (p + q == 1) - dir = 1; + dir = (++p + q == 1) ? 1 : dir; } else if (dir == 1) { - q++; bPos.vz += MAP_CELL_SIZE / 2; - - if (p == q) - dir = 2; + dir = (p == ++q) ? 2 : dir; } else if (dir == 2) { - p--; bPos.vx -= MAP_CELL_SIZE / 2; - - if (p + q == 0) - dir = 3; + dir = (--p + q == 0) ? 3 : dir; } else { - q--; bPos.vz -= MAP_CELL_SIZE / 2; - - if (p == q) - dir = 0; + dir = (p == --q) ? 0 : dir; } - - count++; - }while (count < 1024); + } } @@ -400,40 +427,39 @@ u_int cellsPerFrame = 4; // [D] [T] void BloodyHell(void) { + VECTOR bPos; int dir; - int p; - int q; + int p, q; int px, pz; u_int howMany; int count; - VECTOR bPos; int tile, i; cellsThisFrame = 0; // [A] really it should be based on player's height - bPos.vy = player[0].pos[1] ; - - bPos.vx = player[0].pos[0] & 0xfffffc00; - bPos.vz = player[0].pos[2] & 0xfffffc00; + bPos.vy = player[0].pos[1]; + bPos.vx = player[0].pos[0] & ~1023; + bPos.vz = player[0].pos[2] & ~1023; howMany = cellsPerFrame; if (CameraCnt < 4) howMany = cellsPerFrame + 20; - - q = 0; if (CameraCnt < 8) howMany += 4; + q = 0; p = 0; dir = 0; - count = 0; +#if ENABLE_GAME_FIXES InvalidateMapEnds(); +#endif - do { + for (count = 0; count < 840; count++) + { if (count == 200) howMany--; @@ -446,51 +472,33 @@ void BloodyHell(void) if (i != 0) { DONEMAP_V(px, pz) = tile ^ i; - WunCell(&bPos); - cellsThisFrame++; - - if (cellsThisFrame >= howMany) + if (++cellsThisFrame >= howMany) return; } if (dir == 0) { - p++; bPos.vx += MAP_CELL_SIZE / 2; - - if (p + q == 1) - dir = 1; + dir = (++p + q == 1) ? 1 : dir; } - else if (dir == 1) + else if (dir == 1) { - q++; bPos.vz += MAP_CELL_SIZE / 2; - - if (p == q) - dir = 2; + dir = (p == ++q) ? 2 : dir; } else if (dir == 2) { - p--; - bPos.vx -= MAP_CELL_SIZE / 2; - - if (p + q == 0) - dir = 3; + dir = (--p + q == 0) ? 3 : dir; } - else + else { - q--; bPos.vz -= MAP_CELL_SIZE / 2; - - if (p == q) - dir = 0; + dir = (p == --q) ? 0 : dir; } - - count++; - } while( count < 840 ); + } } int slowWallTests = 0; @@ -503,9 +511,15 @@ int blocked(tNode* v1, tNode* v2) if (slowWallTests != 0) return lineClear((VECTOR*)v1, (VECTOR*)v2) == 0; - x = v1->vx + v1->vx >> 9; + x = v1->vx + v2->vx >> 9; z = v1->vz + v2->vz >> 9; + int prev = DONEMAP_V(x >> 2, z >> 2); + int val = DONEMAP_GETVALUE(x >> 2, z >> 2, prev, 0); + + if (val != 0) + return 1; + return OMAP_GETVALUE(x, z); } @@ -518,10 +532,10 @@ void setDistance(tNode* n, ushort dist) } // [A] -void SetNodeDistanceWithParents(tNode* startNode, ushort dist); +void pushNode(tNode* startNode, ushort dist); // [D] [T] -void iterate(void) +int iterate(void) { tNode pathNodes[8]; @@ -538,16 +552,14 @@ void iterate(void) int r; if (numHeapEntries == 0) - return; + return 0; popNode(&itHere); nbr = pathNodes; // check directions - for(dir = 0; dir < 6; dir++) + for(dir = 0; dir < 6; dir++, nbr++) { - nbr++; - nbr->vx = itHere.vx + dirs[dir].dx; nbr->vy = itHere.vy; nbr->vz = itHere.vz + dirs[dir].dz; @@ -562,39 +574,35 @@ void iterate(void) { if (ABS(nbr->vy - itHere.vy) < 201) { - if ((dist & 1) == 0) - nbr->dist = 0; - + nbr->dist = 0; continue; } } nbr->dist = 1; } - else + else if (dist <= itHere.dist - 288) { - if (dist <= itHere.dist - 288) - { - nbr->dist = 1; - } + nbr->dist = 1; } } // now we have distance let's compute the rest of the map for(dir = 0; dir < 6; dir++) { - if (pathNodes[dir + 1].dist != 0) + // visited? + if (pathNodes[dir].dist != 0) continue; if (dir != 5) - nr = pathNodes[dir + 2].dist; + nr = pathNodes[dir + 1].dist; else - nr = pathNodes[1].dist; + nr = pathNodes[0].dist; if (dir != 0) - nl = pathNodes[dir].dist; + nl = pathNodes[dir - 1].dist; else - nl = pathNodes[6].dist; + nl = pathNodes[5].dist; // uhhmm... distance function selection? if (nl < 2) @@ -604,33 +612,32 @@ void iterate(void) else dist = (nr + itHere.dist >> 1) + 221; } + else if (nr < 2) + { + dist = (nl + itHere.dist >> 1) + 221; + } else { - if (nr < 2) + r = nr - nl; + dist = 0x10000 - (r * r) / 3; + + if (dist < 0) { - dist = (nl + itHere.dist >> 1) + 221; + dist = 0; } else { - r = nr - nl; - dist = 0x10000 - (r * r) / 3; - - if (dist < 0) - { - dist = 0; - } - else - { - a = (dist >> 9) + 128; - dist = dist / a + a >> 1; - } - - dist += itHere.dist; + a = (dist >> 9) + 128; + dist = dist / a + a >> 1; } + + dist += itHere.dist; } - SetNodeDistanceWithParents(&pathNodes[dir + 1], dist); + pushNode(&pathNodes[dir], dist); } + + return numHeapEntries > 0; } // [D] [T] @@ -655,7 +662,7 @@ void InitPathFinding(void) searchTarget.vy = -12367; searchTarget.vz = 0; playerTargetDistanceSq = 0; - pathFrames = 0; + //pathFrames = 0; pathIterations = 129; } @@ -672,7 +679,7 @@ int getInterpolatedDistance(VECTOR* pos) VECTOR sp; // WHY? - n.vx = ((pos->vx + (pos->vz >> 1 & 0x1ffU)) >> 9) * 512 - ((pos->vz & 0x200) >> 1); + n.vx = ((pos->vx + (pos->vz >> 1 & 511)) >> 9) * 512 - ((pos->vz & 512) >> 1); n.vy = pos->vy; n.vz = (pos->vz >> 9) << 9; @@ -855,7 +862,7 @@ void addCivs(void) } // [A] -void SetNodeDistanceWithParents(tNode* startNode, ushort dist) +void pushNode(tNode* node, ushort dist) { int i; u_int pnode, parent; @@ -863,8 +870,9 @@ void SetNodeDistanceWithParents(tNode* startNode, ushort dist) if (numHeapEntries == 198) return; - setDistance(startNode, dist); + setDistance(node, dist); + // up heap i = numHeapEntries + 1; pnode = i; @@ -878,12 +886,12 @@ void SetNodeDistanceWithParents(tNode* startNode, ushort dist) parent >>= 1; } - heap[pnode] = *startNode; + heap[pnode] = *node; numHeapEntries++; } // [A] -void ComputeDistanceFromSearchTarget(tNode* startNode) +void pushSeedNode(tNode* startNode) { u_short dist; int i, dx, dz; @@ -896,7 +904,7 @@ void ComputeDistanceFromSearchTarget(tNode* startNode) dist = SquareRoot0( dx * dx + dz * dz ) >> 1; - SetNodeDistanceWithParents(startNode, dist); + pushNode(startNode, dist); } // [D] [T] @@ -941,14 +949,21 @@ void UpdateCopMap(void) i = 36; while (--i >= 0) - iterate(); + { + if (!iterate()) + { + pathFrames = 0; + break; + } + } DebugDisplayObstacleMap(); // remove cars addCivs(); } - else + + if(pathFrames == 0) { // restart from new search target position if (player[0].playerType == 1 && (CopsCanSeePlayer != 0 || numActiveCops == 0)) @@ -981,7 +996,7 @@ void UpdateCopMap(void) distanceCache[i] = d; } - startNode.vx = ((searchTarget.vx + (searchTarget.vz >> 1 & 0x1ffU)) >> 9) * 512 - ((searchTarget.vz & 0x200U) >> 1); + startNode.vx = ((searchTarget.vx + (searchTarget.vz >> 1 & 511)) >> 9) * 512 - ((searchTarget.vz & 512) >> 1); startNode.vz = (searchTarget.vz >> 9) << 9; startNode.vy = searchTarget.vy; @@ -1003,30 +1018,30 @@ void UpdateCopMap(void) if (dz < dx + dz / 2) { - ComputeDistanceFromSearchTarget(&startNode); + pushSeedNode(&startNode); startNode.vx += 256; startNode.vz += 512; - ComputeDistanceFromSearchTarget(&startNode); + pushSeedNode(&startNode); startNode.vx += 256; startNode.vz -= 512; - ComputeDistanceFromSearchTarget(&startNode); + pushSeedNode(&startNode); } else { - ComputeDistanceFromSearchTarget(&startNode); + pushSeedNode(&startNode); startNode.vx += 256; startNode.vz += 512; - ComputeDistanceFromSearchTarget(&startNode); + pushSeedNode(&startNode); startNode.vx -= 512; - ComputeDistanceFromSearchTarget(&startNode); + pushSeedNode(&startNode); } } diff --git a/src_rebuild/Game/C/pause.c b/src_rebuild/Game/C/pause.c index 5e40c5ac0..9242a33e6 100644 --- a/src_rebuild/Game/C/pause.c +++ b/src_rebuild/Game/C/pause.c @@ -188,32 +188,32 @@ extern void LoadSky(void); void DebugTimeOfDayDay(int direction) { - wantedTimeOfDay = 1; - gTimeOfDay = 1; + wantedTimeOfDay = TIME_DAY; + gTimeOfDay = TIME_DAY; gWantNight = 0; LoadSky(); } void DebugTimeOfDayNight(int direction) { - wantedTimeOfDay = 3; - gTimeOfDay = 3; + wantedTimeOfDay = TIME_NIGHT; + gTimeOfDay = TIME_NIGHT; gWantNight = 1; LoadSky(); } void DebugTimeOfDayDusk(int direction) { - wantedTimeOfDay = 0; - gTimeOfDay = 0; + wantedTimeOfDay = TIME_DUSK; + gTimeOfDay = TIME_DUSK; gWantNight = 0; LoadSky(); } void DebugTimeOfDayDawn(int direction) { - wantedTimeOfDay = 2; - gTimeOfDay = 2; + wantedTimeOfDay = TIME_DAWN; + gTimeOfDay = TIME_DAWN; gWantNight = 0; LoadSky(); } @@ -225,7 +225,7 @@ void DebugTimeOfDayRain(int direction) gWeather ^= 1; wantedWeather = gWeather; - if (gWeather == 1) + if (gWeather == WEATHER_RAIN) wetness = 7000; else wetness = 0; @@ -259,7 +259,6 @@ MENU_HEADER DebugJustForFunHeader = MENU_ITEM DebugOptionsItems[] = { #ifdef CUTSCENE_RECORDER - //{ gCutsceneRecorderPauseText, 5u, 2u, (pauseFunc)&NextCutsceneRecorderPlayer, MENU_QUIT_NONE, NULL }, { gCurrentChasePauseText, 5u, 2u, (pauseFunc)&CutRec_NextChase, MENU_QUIT_NONE, NULL }, #endif { "Display position", PAUSE_TYPE_FUNC, 2, SetDisplayPosition, MENU_QUIT_NONE, NULL}, @@ -1062,7 +1061,7 @@ void DrawVisibleMenus(void) if (NumPlayers > 1) { - SetFullscreenDrawing(); + SetFullscreenDrawing(2); } pActive = VisibleMenus[VisibleMenu]; diff --git a/src_rebuild/Game/C/pedest.c b/src_rebuild/Game/C/pedest.c index 61ddf2e3e..2160b00dd 100644 --- a/src_rebuild/Game/C/pedest.c +++ b/src_rebuild/Game/C/pedest.c @@ -24,6 +24,7 @@ #include "map.h" #include "system.h" #include "handling.h" +#include "draw.h" #include "ASM/rndrasm.h" @@ -1433,7 +1434,7 @@ void PingInPedestrians(void) baseLoc.vy = player[0].pos[1]; baseLoc.vz = player[0].pos[2]; - if (gWeather == 0 && FindSeated() != NULL) + if (gWeather == WEATHER_NONE && FindSeated() != NULL) return; for (i = 0; i < 50; i++) @@ -2085,8 +2086,8 @@ int CalcPedestrianDirection(int last_dir, int wx, int wz, VECTOR* target) } } - rx = wx & 0xfffffc00; - rz = wz & 0xfffffc00; + rx = wx & ~1023; + rz = wz & ~1023; if (num == 1) { @@ -2553,7 +2554,7 @@ void IHaveThePower(void) { oldWeather = gWeather; bPower = 1; - gWeather = 1; + gWeather = WEATHER_RAIN; } powerCounter++; @@ -2587,12 +2588,11 @@ void IHaveThePower(void) // [D] [T] void ProcessTannerPad(LPPEDESTRIAN pPed, u_int pad, char PadSteer, char use_analogue) { + int mapheight[2]; + sdPlane* SurfacePtr; - int direction; - VECTOR vec; - VECTOR normal; - VECTOR out; - VECTOR tVec; + int direction, diff; + VECTOR vec, normal, out, tVec; sdPlane* plane; PLAYER* lcp; @@ -2631,23 +2631,21 @@ void ProcessTannerPad(LPPEDESTRIAN pPed, u_int pad, char PadSteer, char use_anal bStopTanner = 0; - int mapheight[2]; - mapheight[0] = -130 - MapHeight(&vec); mapheight[1] = -130 - MapHeight(&tVec); - int dist = ABS(mapheight[1] - mapheight[0]); + diff = ABS(mapheight[1] - mapheight[0]); // check slope - if (dist <= 1010) + if (diff <= 1010) { SurfacePtr = sdGetCell(&tVec); if (SurfacePtr != NULL) { - dist = ABS(((SurfacePtr->b >> 2) - 2048 & 0xfff) - 2048); + diff = ABS(DIFF_ANGLES((SurfacePtr->b >> 2), 0)); //ABS(((SurfacePtr->b >> 2) - 2048 & 0xfff) - 2048); - if (dist <= 1100) + if (diff <= 1100) { switch (SurfacePtr->surface) { @@ -2656,7 +2654,7 @@ void ProcessTannerPad(LPPEDESTRIAN pPed, u_int pad, char PadSteer, char use_anal //case 6: // water. We allow to walk on water in Rio a little bit. Then he drowns case 9: // water with fade out default: - dist = -1; + diff = -1; break; } } @@ -2664,7 +2662,7 @@ void ProcessTannerPad(LPPEDESTRIAN pPed, u_int pad, char PadSteer, char use_anal } // can't walk in water - if (dist != -1) + if (diff != -1) bStopTanner = 1; if (pPed->type != PED_ACTION_SIT && !bStopTanner) @@ -2765,10 +2763,11 @@ void ProcessTannerPad(LPPEDESTRIAN pPed, u_int pad, char PadSteer, char use_anal { FindSurfaceD2((VECTOR*)lcp->pos, &normal, &out, &plane); - if (plane->surface != -1 && plane->surface < 32 && (plane->surface & 0x10)) + if (plane && plane->surface != -1 && plane->surface < 32 && (plane->surface & 16)) { pPed->position.vx += (normal.vx >> 6); pPed->position.vz += (normal.vz >> 6); + pPed->position.vy = mapheight[0]; } } } diff --git a/src_rebuild/Game/C/players.c b/src_rebuild/Game/C/players.c index 18111b519..1ef118c0f 100644 --- a/src_rebuild/Game/C/players.c +++ b/src_rebuild/Game/C/players.c @@ -148,11 +148,13 @@ void ChangeCarPlayerToPed(int playerID) if (CarHasSiren(lcp->ap.model)) locPlayer->horn.on = 0; +#if ENABLE_MISSION_FIXES // [A] carry over felony from car to Tanner if cops see player // don't clear player felony in Destroy the Yard if (CopsCanSeePlayer || gCurrentMissionNumber == 30) pedestrianFelony = lcp->felonyRating; else +#endif pedestrianFelony = 0; } @@ -207,10 +209,12 @@ void ChangePedPlayerToCar(int playerID, CAR_DATA *newCar) newCar->ai.padid = &lPlayer->padid; newCar->hndType = 0; - if (playerID == 0 && - !(newCar->controlFlags & CONTROL_FLAG_PLAYER_START_CAR)) // [A] bug fix: don't give felony if player owns his cop car + if (playerID == 0 +#if ENABLE_GAME_FIXES + && !(newCar->controlFlags & CONTROL_FLAG_PLAYER_START_CAR) // [A] bug fix: don't give felony if player owns his cop car +#endif + ) { - // [A] Rev 1.1 removes felony override for "Steal the cop car" if (gCurrentMissionNumber != 32 && MissionHeader->residentModels[newCar->ap.model] == 0) { NoteFelony(&felonyData, 11, 4096); @@ -230,12 +234,14 @@ void ChangePedPlayerToCar(int playerID, CAR_DATA *newCar) HaveCarSoundStraightAway(playerID); // [A] carry over felony from Tanner to car if cops see player. Force in Destroy the yard +#if ENABLE_MISSION_FIXES if (CopsCanSeePlayer || gCurrentMissionNumber == 30) { if (newCar->felonyRating < pedestrianFelony) newCar->felonyRating = pedestrianFelony; } else +#endif pedestrianFelony = 0; } diff --git a/src_rebuild/Game/C/pres.c b/src_rebuild/Game/C/pres.c index 928fed71c..d266cc840 100644 --- a/src_rebuild/Game/C/pres.c +++ b/src_rebuild/Game/C/pres.c @@ -3,6 +3,318 @@ #include "system.h" #include "texture.h" +extern int gShowMap; + +#ifndef PSX + +#include "PsyX/PsyX_render.h" +#include "../utils/targa.h" +#include "../utils/hqfont.h" + +#define HIRES_FONTS + +struct FONT_QUAD +{ + float x0, y0, s0, t0; // top-left + float x1, y1, s1, t1; // bottom-right +}; + +TextureID gHiresFontTexture = 0; +TextureID gHiresDigitsTexture = 0; + +OUT_FN2RANGE gHiresFontRanges[4]; +OUT_FN2INFO gHiresFontCharData[4][224]; +int gHiresFontRangeCount = 0; + +void InitHiresFonts() +{ + char namebuffer[64]; + u_char* data; + + // init digits + if(!gHiresDigitsTexture) + { + int width, height, bpp; + + sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\digits.tga"); + FS_FixPathSlashes(namebuffer); + + if (LoadTGAImage(namebuffer, &data, width, height, bpp)) + { + if (bpp == 32) + { + gHiresDigitsTexture = GR_CreateRGBATexture(width, height, data); + } + free(data); + data = NULL; + } + } + + // init font2 + if(!gHiresFontTexture) + { + gHiresFontRangeCount = 0; + + int width, height, bpp; + int x, y; + int size; + FILE* fp; + sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\font2.fn2"); + FS_FixPathSlashes(namebuffer); + + fp = fopen(namebuffer, "rb"); + if (fp) + { + int i; + + // read fn2 step by step + OUT_FN2HEADER fn2hdr; + fread(&fn2hdr, sizeof(fn2hdr), 1, fp); + + gHiresFontRangeCount = fn2hdr.range_count; + for (i = 0; i < fn2hdr.range_count; ++i) + { + fread(&gHiresFontRanges[i], sizeof(gHiresFontRanges[i]), 1, fp); + fread(gHiresFontCharData[i], sizeof(OUT_FN2INFO), gHiresFontRanges[i].count, fp); + } + + fclose(fp); + } + + // load TGA file + sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\font2.tga"); + FS_FixPathSlashes(namebuffer); + + if (LoadTGAImage(namebuffer, &data, width, height, bpp)) + { + if (bpp == 32) + { + gHiresFontTexture = GR_CreateRGBATexture(HIRES_FONT_SIZE_W, HIRES_FONT_SIZE_H, data); + } + free(data); + } + } +} + +void SetHiresFontTexture(int enabled) +{ + if (gHiresFontTexture == 0) + { + return; + } + + DR_PSYX_TEX* tex = (DR_PSYX_TEX*)current->primptr; + if (enabled) + SetPsyXTexture(tex, gHiresFontTexture, 255, 255); + else + SetPsyXTexture(tex, 0, 0, 0); + + if (gShowMap == 0) + { + addPrim(current->ot, tex); + current->primptr += sizeof(DR_PSYX_TEX); + } + else + { + DrawPrim(tex); + } +} + +void SetHiresDigitsTexture(int enabled) +{ + if (gHiresDigitsTexture == 0) + { + return; + } + + DR_PSYX_TEX* tex = (DR_PSYX_TEX*)current->primptr; + if (enabled) + SetPsyXTexture(tex, gHiresDigitsTexture, 96, 59); + else + SetPsyXTexture(tex, 0, 0, 0); + + addPrim(current->ot, tex); + current->primptr += sizeof(DR_PSYX_TEX); +} + +void GetHiresBakedQuad(int char_index, float* xpos, float* ypos, FONT_QUAD* q) +{ + float ipw = 1.0f / (float)HIRES_FONT_SIZE_W; + float iph = 1.0f / (float)HIRES_FONT_SIZE_H; + + const OUT_FN2INFO* b = gHiresFontCharData[0] + char_index - gHiresFontRanges[0].start; + + float scale = 0.275f; + + float s_x = b->x1 - b->x0; + float s_y = b->y1 - b->y0; + + q->x0 = *xpos + b->xoff * scale; + q->y0 = *ypos + b->yoff * scale; + q->x1 = (b->xoff2 - b->xoff) * scale; + q->y1 = (b->yoff2 - b->yoff) * scale; + + q->s0 = b->x0 * 255.0f * ipw; + q->t0 = b->y0 * 255.0f * iph; + q->s1 = s_x * 255.0f * ipw; + q->t1 = s_y * 255.0f * iph; + + q->y0 += 14.0f; + + *xpos += b->xadvance * scale; +} + +int StrighWidthHires(char* string) +{ + u_char chr; + float width; + width = 0; + + while ((chr = *string++) != 0) + { + if (chr >= 128 && chr <= 138) + { + width += 24; + continue; + } + + chr = (chr >= 32 && chr < 128 || chr > 138) ? chr : '?'; + + float fx, fy; + fx = 0.0f; + fy = 0.0f; + FONT_QUAD q; + GetHiresBakedQuad(chr, &fx, &fy, &q); + width += fx; + } + return width; +} + +extern CVECTOR gFontColour; +extern short fontclutid; +extern short fonttpage; + +int PrintStringHires(char* string, int x, int y) +{ + u_char chr; + float width; + u_int index; + int showMap; + + showMap = gShowMap; + width = x; + + SetHiresFontTexture(showMap); + + while ((chr = *string++) != 0) + { + if (chr >= 128 && chr <= 138) + { + if(showMap) + SetHiresFontTexture(0); + else + SetHiresFontTexture(1); + + current->primptr = (char*)DrawButton(chr, current->primptr, width, y); + + if (showMap) + SetHiresFontTexture(1); + else + SetHiresFontTexture(0); + + width += 24; + x += 24; + continue; + } + + chr = (chr >= 32 && chr < 128 || chr > 138) ? chr : '?'; + + POLY_FT4* fontFT4; + POLY_FT4* shadowFT4; + float fx, fy; + fx = width; + fy = y; + FONT_QUAD q; + GetHiresBakedQuad(chr, &fx, &fy, &q); + + fontFT4 = (POLY_FT4*)current->primptr; + + setPolyFT4(fontFT4); + setSemiTrans(fontFT4, 1); + + setUVWH(fontFT4, q.s0, q.t0, q.s1, q.t1); + + fontFT4->clut = fontclutid; + fontFT4->tpage = fonttpage; + + if (showMap == 0) + { + setRGB0(fontFT4, gFontColour.r, gFontColour.g, gFontColour.b); + setXYWH(fontFT4, q.x0, q.y0, q.x1, q.y1); + + addPrim(current->ot, fontFT4); + current->primptr += sizeof(POLY_FT4); + + shadowFT4 = (POLY_FT4*)current->primptr; + + // add shadow poly + memcpy(shadowFT4, fontFT4, sizeof(POLY_FT4)); + setRGB0(shadowFT4, 0, 0, 0); + setXYWH(shadowFT4, q.x0 + 0.5f, q.y0 + 0.5f, q.x1, q.y1); + + addPrim(current->ot, shadowFT4); + current->primptr += sizeof(POLY_FT4); + } + else + { + setRGB0(fontFT4, 0, 0, 0); + setXYWH(fontFT4, q.x0 + 0.5f, q.y0 + 0.5f, q.x1, q.y1); + DrawPrim(fontFT4); + + setRGB0(fontFT4, gFontColour.r, gFontColour.g, gFontColour.b); + setXYWH(fontFT4, q.x0, q.y0, q.x1, q.y1); + DrawPrim(fontFT4); + } + + width += fx - width; + } + + SetHiresFontTexture(showMap == 0); + if(showMap) + DrawSync(0); + + return width; +} + +void PrintStringBoxedHires(char* string, int ix, int iy) +{ + char word[32]; + int x, y; + int wordcount; + + wordcount = 1; + + x = ix; + y = iy; + + while (*string) + { + string = GetNextWord(string, word); + + if (x + StringWidth(word) > 308 && (wordcount != 1 || *string != 0)) + { + x = ix; + y += 14; + } + + x = PrintStringHires(word, x, y); + + wordcount++; + } +} + +#endif + extern TEXTURE_DETAILS digit_texture; struct FONT_DIGIT @@ -61,6 +373,13 @@ void SetTextColour(u_char Red, u_char Green, u_char Blue) // [D] [T] int StringWidth(char *pString) { +#ifdef HIRES_FONTS + if (gHiresFontTexture) + { + return StrighWidthHires(pString); + } +#endif + u_char let; int w; @@ -166,14 +485,18 @@ void LoadFont(char *buffer) fonttpage = GetTPage(0,0, dest.x, dest.y); - LoadImage(&fontclutpos, (u_long *)clut); // upload clut - LoadImage(&dest, (u_long *)(file + 32)); // upload font image + LoadImage(&fontclutpos, (u_long*)clut); // upload clut + LoadImage(&dest, (u_long*)(file + 32)); // upload font image + +#ifdef HIRES_FONTS + InitHiresFonts(); +#endif DrawSync(0); } // [D] [T] -void StoreClut2(u_long *pDest, int x, int y) +void StoreClut2(u_long* pDest, int x, int y) { RECT16 rect; @@ -196,7 +519,7 @@ void SetCLUT16Flags(ushort clutID, ushort mask, char transparent) x = (clutID & 63) * 16; y = (clutID >> 6); - StoreClut2((ulong *)buffer, x, y); + StoreClut2((u_long*)buffer, x, y); pCurrent = buffer; ctr = 1; @@ -217,9 +540,6 @@ void SetCLUT16Flags(ushort clutID, ushort mask, char transparent) LoadClut2((u_long*)buffer, x,y); } -// MAP.C ???? -extern int gShowMap; - // [D] [T] int PrintString(char *string, int x, int y) { @@ -233,10 +553,19 @@ int PrintString(char *string, int x, int y) if (current == NULL) return -1; +#ifdef HIRES_FONTS + if (gHiresFontTexture) + { + return PrintStringHires(string, x, y); + } +#endif + font = (SPRT *)current->primptr; if (showMap != 0) - font = (SPRT *)SetFontTPage(font); + { + font = (SPRT*)SetFontTPage(font); + } width = x; @@ -247,7 +576,7 @@ int PrintString(char *string, int x, int y) width += 4; continue; } - + if (chr < 32 || chr > 138 || chr < 128) { if (AsciiTable[chr] == -1) @@ -287,18 +616,24 @@ int PrintString(char *string, int x, int y) else { if (showMap == 0) - font = (SPRT *)SetFontTPage(font); + { + font = (SPRT*)SetFontTPage(font); + } font = (SPRT *)DrawButton(chr, font, width, y); width += 24; if (showMap != 0) - font = (SPRT *)SetFontTPage(font); + { + font = (SPRT*)SetFontTPage(font); + } } } if (showMap == 0) - current->primptr = (char *)SetFontTPage(font); + { + current->primptr = (char*)SetFontTPage(font); + } else DrawSync(0); @@ -316,6 +651,10 @@ short PrintDigit(int x, int y, char *string) int fixedWidth; char vOff, h; +#ifdef HIRES_FONTS + SetHiresDigitsTexture(0); +#endif + width = x; font = (SPRT *)current->primptr; @@ -356,8 +695,18 @@ short PrintDigit(int x, int y, char *string) font->x0 = width + (fixedWidth - pDigit->width) / 2; font->y0 = y; - font->u0 = digit_texture.coords.u0 + pDigit->xOffset; - font->v0 = vOff + digit_texture.coords.v0; +#ifdef HIRES_FONTS + if (gHiresDigitsTexture) + { + font->u0 = pDigit->xOffset; + font->v0 = vOff; + } + else +#endif + { + font->u0 = digit_texture.coords.u0 + pDigit->xOffset; + font->v0 = digit_texture.coords.v0 + vOff; + } font->w = pDigit->width; font->h = h; @@ -388,6 +737,10 @@ short PrintDigit(int x, int y, char *string) addPrim(current->ot, null); current->primptr += sizeof(POLY_FT3); +#ifdef HIRES_FONTS + SetHiresDigitsTexture(1); +#endif + return width; } @@ -408,6 +761,14 @@ void PrintStringBoxed(char *string, int ix, int iy) int index; int wordcount; +#ifdef HIRES_FONTS + if (gHiresFontTexture) + { + PrintStringBoxedHires(string, ix, iy); + return; + } +#endif + font = (SPRT *)current->primptr; wordcount = 1; @@ -508,10 +869,16 @@ int PrintScaledString(int y, char *string, int scale) int height; u_char vOff; +#ifdef HIRES_FONTS + SetHiresDigitsTexture(0); +#endif + font = (POLY_FT4 *)current->primptr; if (gShowMap != 0) - font = (POLY_FT4 *)SetFontTPage(font); + { + font = (POLY_FT4*)SetFontTPage(font); + } width = StringWidth(string) * scale; x = (320 - (width / 16)) / 2; @@ -548,6 +915,7 @@ int PrintScaledString(int y, char *string, int scale) x1 = x + width; setPolyFT4(font); + setSemiTrans(font, 1); setRGB0(font, gFontColour.r, gFontColour.g, gFontColour.b); font->x0 = x; // [A] no suitable macro in libgpu @@ -559,7 +927,16 @@ int PrintScaledString(int y, char *string, int scale) font->x3 = x1; font->y3 = y1; - setUVWH(font, digit_texture.coords.u0 + pDigit->xOffset, digit_texture.coords.v0 + vOff, pDigit->width, height); +#ifdef HIRES_FONTS + if (gHiresDigitsTexture) + { + setUVWH(font, pDigit->xOffset, vOff, pDigit->width, height); + } + else +#endif + { + setUVWH(font, digit_texture.coords.u0 + pDigit->xOffset, digit_texture.coords.v0 + vOff, pDigit->width, height); + } font->clut = digit_texture.clutid; font->tpage = digit_texture.tpageid; @@ -574,6 +951,10 @@ int PrintScaledString(int y, char *string, int scale) current->primptr = (char*)font; +#ifdef HIRES_FONTS + SetHiresDigitsTexture(1); +#endif + return x; } @@ -605,7 +986,7 @@ void* DrawButton(u_char button, void *prim, int x, int y) SPRT* sprt; POLY_FT3* null; - btn = &button_textures[button - 0x80]; + btn = &button_textures[button - 128]; sprt = (SPRT*)prim; setSprt(sprt); diff --git a/src_rebuild/Game/C/pres.h b/src_rebuild/Game/C/pres.h index 821814c09..4c95890f6 100644 --- a/src_rebuild/Game/C/pres.h +++ b/src_rebuild/Game/C/pres.h @@ -3,12 +3,9 @@ struct OUT_FONTINFO { - u_char x; - u_char y; - char offx; - char offy; - u_char width; - u_char height; + u_char x, y; + char offx, offy; + u_char width, height; u_short pad; }; diff --git a/src_rebuild/Game/C/replays.c b/src_rebuild/Game/C/replays.c index 945882825..b69a720c8 100644 --- a/src_rebuild/Game/C/replays.c +++ b/src_rebuild/Game/C/replays.c @@ -135,7 +135,7 @@ int SaveReplayToBuffer(char *buffer) header->wantedCar[0] = wantedCar[0]; header->wantedCar[1] = wantedCar[1]; - memcpy((u_char*)&header->SavedData, (u_char*)&MissionEndData, sizeof(MISSION_DATA)); + header->SavedData = MissionEndData; // write each stream data for (int i = 0; i < NumPlayers; i++) @@ -146,7 +146,7 @@ int SaveReplayToBuffer(char *buffer) REPLAY_STREAM* srcStream = &ReplayStreams[i]; // copy source type - memcpy((u_char*)&sheader->SourceType, (u_char*)&srcStream->SourceType, sizeof(STREAM_SOURCE)); + sheader->SourceType = srcStream->SourceType; sheader->Size = srcStream->padCount * sizeof(PADRECORD); // srcStream->PadRecordBufferEnd - srcStream->InitialPadRecordBuffer; sheader->Length = srcStream->length; @@ -214,7 +214,7 @@ int LoadReplayFromBuffer(char *buffer) wantedCar[0] = header->wantedCar[0]; wantedCar[1] = header->wantedCar[1]; - memcpy((u_char*)&MissionEndData, (u_char*)&header->SavedData, sizeof(MISSION_DATA)); + MissionEndData = header->SavedData; pt = (char*)(header+1); @@ -227,7 +227,7 @@ int LoadReplayFromBuffer(char *buffer) REPLAY_STREAM* destStream = &ReplayStreams[i]; // copy source type - memcpy((u_char*)&destStream->SourceType, (u_char*)&sheader->SourceType, sizeof(STREAM_SOURCE)); + destStream->SourceType = sheader->SourceType; int size = (sheader->Size + sizeof(PADRECORD)) & -4; @@ -278,50 +278,11 @@ int LoadReplayFromBuffer(char *buffer) return 1; } -#ifndef PSX -int LoadUserAttractReplay(int mission, int userId) -{ - char customFilename[64]; - - if (userId >= 0 && userId < gNumUserChases) - { - sprintf(customFilename, "REPLAYS\\User\\%s\\ATTRACT.%d", gUserReplayFolderList[userId], mission); - - if (FileExists(customFilename)) - { - if (Loadfile(customFilename, (char*)_other_buffer)) - return LoadReplayFromBuffer((char*)_other_buffer); - } - } - - return 0; -} -#endif - // [D] [T] int LoadAttractReplay(int mission) { char filename[32]; -#ifndef PSX - int userId = -1; - - // [A] REDRIVER2 PC - custom attract replays - if (gNumUserChases) - { - userId = rand() % (gNumUserChases + 1); - - if (userId == gNumUserChases) - userId = -1; - } - - if (LoadUserAttractReplay(mission, userId)) - { - printInfo("Loaded custom attract replay (%d) by %s\n", mission, gUserReplayFolderList[userId]); - return 1; - } -#endif - sprintf(filename, "REPLAYS\\ATTRACT.%d", mission); if (!FileExists(filename)) diff --git a/src_rebuild/Game/C/shadow.c b/src_rebuild/Game/C/shadow.c index 6d3aee030..66336ec0f 100644 --- a/src_rebuild/Game/C/shadow.c +++ b/src_rebuild/Game/C/shadow.c @@ -66,7 +66,7 @@ void ResetTyreTracks(CAR_DATA* cp, int player_id) // [D] [T] void GetTyreTrackPositions(CAR_DATA *cp, int player_id) { - int loop, track, steps; + int loop, track; CAR_COSMETICS *car_cos; VECTOR WheelPos; VECTOR CarPos; @@ -78,9 +78,8 @@ void GetTyreTrackPositions(CAR_DATA *cp, int player_id) car_cos = cp->ap.carCos; SetRotMatrix(&cp->hd.where); - steps = 4 / MAX_TYRE_TRACK_WHEELS; - - for (loop = 0; loop < 4; loop += steps) + track = 0; + for (loop = (2 / MAX_TYRE_TRACK_WHEELS); loop < 4; loop += (4 / MAX_TYRE_TRACK_WHEELS), track++) { WheelPos.vx = car_cos->wheelDisp[loop].vx; if (loop & 2) @@ -89,7 +88,7 @@ void GetTyreTrackPositions(CAR_DATA *cp, int player_id) WheelPos.vx -= 17; WheelPos.vy = 0; - WheelPos.vz = car_cos->wheelDisp[loop + 1 & 3].vz; + WheelPos.vz = car_cos->wheelDisp[loop].vz; _MatrixRotate(&WheelPos); @@ -97,8 +96,6 @@ void GetTyreTrackPositions(CAR_DATA *cp, int player_id) WheelPos.vy = CarPos.vy; WheelPos.vz += CarPos.vz; - track = loop / steps; - tyre_new_positions[player_id][track].vx = WheelPos.vx; tyre_new_positions[player_id][track].vz = WheelPos.vz; tyre_new_positions[player_id][track].vy = MapHeight(&WheelPos); @@ -442,7 +439,7 @@ void InitShadow(void) } // [D] [A] - this is a fuckery -void SubdivShadow(long z0, long z1, long z2, long z3, POLY_FT4 *sps) +void SubdivShadow(int z0, int z1, int z2, int z3, POLY_FT4 *sps) { // [A] we already have better car shadow code. This is UNUSED anyway POLY_FT4 *spd; @@ -493,8 +490,8 @@ void PlaceShadowForCar(VECTOR *shadowPoints, int subdiv, int zOfs, int flag) POLYFT4* pft4 = &shadowpoly; - plotContext.clut = (u_int)(*plotContext.ptexture_cluts)[pft4->texture_set][pft4->texture_id] << 0x10; - plotContext.tpage = ((u_int)(*plotContext.ptexture_pages)[pft4->texture_set] | 0x40) << 0x10; + plotContext.clut = (u_int)(*plotContext.ptexture_cluts)[pft4->texture_set][pft4->texture_id]; + plotContext.tpage = ((u_int)(*plotContext.ptexture_pages)[pft4->texture_set] | 0x40); copyVector(&subdivVerts[0][0], &points[pft4->v0]); subdivVerts[0][0].uv.val = *(ushort*)&pft4->uv0; @@ -656,7 +653,7 @@ void clippedPoly(void) int iVar6; SVECTOR *pSVar7; short *psVar8; - ulong *in_a1; + uint *in_a1; short *psVar9; int iVar10; int iVar11; @@ -665,7 +662,7 @@ void clippedPoly(void) pPVar4 = spolys; iVar11 = numcv + -1; if (iVar11 != -1) { - in_a1 = (ulong *)0xffffffff; + in_a1 = (uint *)0xffffffff; psVar8 = &(&cv)[lastcv].vz; do { iVar11 = iVar11 + -1; @@ -677,7 +674,7 @@ void clippedPoly(void) if (2 < numcv) { iVar11 = numcv + -1; if (numcv != 0) { - in_a1 = (ulong *)0xffffffff; + in_a1 = (uint *)0xffffffff; pSVar7 = &cv + lastcv; do { iVar11 = iVar11 + -1; @@ -689,7 +686,7 @@ void clippedPoly(void) if (2 < numcv) { iVar11 = numcv + -1; if (numcv != 0) { - in_a1 = (ulong *)&(&cv)[lastcv].vy; + in_a1 = (uint *)&(&cv)[lastcv].vy; do { iVar11 = iVar11 + -1; *(short *)((int)in_a1 + 2) = @@ -701,7 +698,7 @@ void clippedPoly(void) if (2 < numcv) { iVar11 = numcv + -1; if (numcv != 0) { - in_a1 = (ulong *)0xffffffff; + in_a1 = (uint *)0xffffffff; psVar8 = &(&cv)[lastcv].vy; do { iVar11 = iVar11 + -1; @@ -713,7 +710,7 @@ void clippedPoly(void) if (2 < numcv) { iVar11 = numcv + -1; if (numcv != 0) { - in_a1 = (ulong *)0xffffffff; + in_a1 = (uint *)0xffffffff; psVar8 = &(&cv)[lastcv].vy; do { iVar11 = iVar11 + -1; diff --git a/src_rebuild/Game/C/shadow.h b/src_rebuild/Game/C/shadow.h index 629a6338e..e0cbf4cb9 100644 --- a/src_rebuild/Game/C/shadow.h +++ b/src_rebuild/Game/C/shadow.h @@ -16,7 +16,7 @@ extern void AddTyreTrack(int wheel, int tracksAndSmoke, int player_id, int conti extern void DrawTyreTracks(); // 0x000759E0 -extern void SubdivShadow(long z0, long z1, long z2, long z3, POLY_FT4 *sps); // 0x00076108 +extern void SubdivShadow(int z0, int z1, int z2, int z3, POLY_FT4 *sps); // 0x00076108 extern void PlaceShadowForCar(VECTOR *shadowPoints, int subdiv, int zOfs, int flag); // 0x000766CC extern void sQuad(SVECTOR *v0, SVECTOR *v1, SVECTOR *v2, SVECTOR *v3, CVECTOR* light_col, int LightSortCorrect); // 0x00077138 diff --git a/src_rebuild/Game/C/sky.c b/src_rebuild/Game/C/sky.c index 90bfd64d3..65cf854ef 100644 --- a/src_rebuild/Game/C/sky.c +++ b/src_rebuild/Game/C/sky.c @@ -8,13 +8,11 @@ #include "main.h" #include "debris.h" #include "players.h" +#include "draw.h" struct RGB16 { - short r; - short g; - short b; - short pad; + short r, g, b, pad; }; struct FLAREREC @@ -259,20 +257,20 @@ void LoadSky(void) if (gWeather - 1U < 2) { - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) offset = 0x10000; else offset = 0x20000; } else { - if (gTimeOfDay == 0) + if (gTimeOfDay == TIME_DAWN) offset = 0x30000; - else if (gTimeOfDay == 1) + else if (gTimeOfDay == TIME_DAY) offset = 0; - else if (gTimeOfDay == 2) + else if (gTimeOfDay == TIME_DUSK) offset = 0x40000; - else if (gTimeOfDay == 3) + else if (gTimeOfDay == TIME_NIGHT) offset = 0x10000; } @@ -287,7 +285,7 @@ void LoadSky(void) } // [D] [T] -#ifdef USE_PGXP +#if USE_PGXP void DisplaySun(DVECTORF* pos, CVECTOR* col, int flare_col) #else void DisplaySun(DVECTOR* pos, CVECTOR* col, int flare_col) @@ -395,7 +393,7 @@ void DisplaySun(DVECTOR* pos, CVECTOR* col, int flare_col) } // [D] [T] -#ifdef USE_PGXP +#if USE_PGXP void DisplayMoon(DVECTORF* pos, CVECTOR* col, int flip) #else void DisplayMoon(DVECTOR* pos, CVECTOR* col, int flip) @@ -494,7 +492,7 @@ void DrawLensFlare(void) int haze_col; -#ifdef USE_PGXP +#if USE_PGXP DVECTORF sun_pers_conv_position; #else DVECTOR sun_pers_conv_position; @@ -505,10 +503,10 @@ void DrawLensFlare(void) source = sun_source; - if (gWeather - 1U <= 1 || gTimeOfDay == 0 || gTimeOfDay == 2) + if (gWeather - 1U <= 1 || (M_BIT(gTimeOfDay) & (M_BIT(TIME_DAWN) | M_BIT(TIME_DUSK)))) return; - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) col.r = 128; else col.r = 254; @@ -519,7 +517,7 @@ void DrawLensFlare(void) col.b = col.r; // get the sun brightness from framebuffer copy - if (gTimeOfDay != 3 && last_attempt_failed == 0) + if (gTimeOfDay != TIME_NIGHT && last_attempt_failed == 0) { pwBuffer = buffer; StoreImage(&source, (u_long*)buffer); @@ -548,7 +546,7 @@ void DrawLensFlare(void) gte_SetRotMatrix(&inv_camera_matrix); gte_SetTransVector(&dummy); - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { gte_ldv0(&moon_position[GameLevel]); } @@ -570,7 +568,7 @@ void DrawLensFlare(void) distance_to_sun = SquareRoot0(xgap * xgap + ygap * ygap); - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) { if (distance_to_sun < 500) { @@ -646,7 +644,7 @@ void DrawLensFlare(void) } } -#ifdef USE_PGXP +#if USE_PGXP // remap PsyX_GetPSXWidescreenMappedViewport(&viewp); sun_pers_conv_position.vx = RemapVal(sun_pers_conv_position.vx, float(viewp.x), float(viewp.w), 0.0f, 320.0f); @@ -687,8 +685,6 @@ void DrawLensFlare(void) int gTunnelNum = -1; int skyFade; -RGB16 skycolor = { 128,128,128 }; - // [D] [T] void TunnelSkyFade(void) { @@ -697,9 +693,7 @@ void TunnelSkyFade(void) VECTOR* v2; VECTOR* v1; int tun; - - if (gTunnelNum == -1) - return; + int px, pz; if (GameLevel != 3 && gTunnelNum < 3) tun = gTunnelNum; @@ -718,13 +712,16 @@ void TunnelSkyFade(void) if (DIFF_ANGLES(camera_angle.vy, tunnelDir[tun][1]) + 1247 < 2495) // (((tunnelDir[tun][1] - camera_angle.vy) + 2048 & 4095) - 801 < 2495) v2 = &tunnelPos[tun][1]; + px = player[0].pos[0]; + pz = player[0].pos[2]; + if(v1 && v2) { - dX = (v1->vx - player[0].pos[0]) >> 5; // [A] smooth sky fade - dZ = (v1->vz - player[0].pos[2]) >> 5; + dX = (v1->vx - px) >> 5; // [A] smooth sky fade + dZ = (v1->vz - pz) >> 5; - diffX = (v2->vx - player[0].pos[0]) >> 5; - diffZ = (v2->vz - player[0].pos[2]) >> 5; + diffX = (v2->vx - px) >> 5; + diffZ = (v2->vz - pz) >> 5; len = (dX * dX + dZ * dZ); l2 = (diffX * diffX + diffZ * diffZ); @@ -734,15 +731,15 @@ void TunnelSkyFade(void) } else if(v2) { - diffX = (v2->vx - player[0].pos[0]) >> 5; - diffZ = (v2->vz - player[0].pos[2]) >> 5; + diffX = (v2->vx - px) >> 5; + diffZ = (v2->vz - pz) >> 5; len = (diffX * diffX + diffZ * diffZ); } else if(v1) { - diffX = (v1->vx - player[0].pos[0]) >> 5; - diffZ = (v1->vz - player[0].pos[2]) >> 5; + diffX = (v1->vx - px) >> 5; + diffZ = (v1->vz - pz) >> 5; len = (diffX * diffX + diffZ * diffZ); } @@ -762,41 +759,41 @@ void TunnelSkyFade(void) } // [D] [T] -void calc_sky_brightness(void) +void calc_sky_brightness(RGB16* skycolor) { int dawn; dawn = DawnCount >> 5; - if(gTimeOfDay == 0 || gTimeOfDay == 2) + if(M_BIT(gTimeOfDay) & (M_BIT(TIME_DAWN) | M_BIT(TIME_DUSK))) { - if (gTimeOfDay == 0) + if (gTimeOfDay == TIME_DAWN) { - skycolor.r = dawn + 41; - skycolor.b = dawn + 28; + skycolor->r = dawn + 41; + skycolor->b = dawn + 28; } - else if (gTimeOfDay == 2) + else if (gTimeOfDay == TIME_DUSK) { - skycolor.r = 143 - dawn; - skycolor.b = 128 - dawn; + skycolor->r = 143 - dawn; + skycolor->b = 128 - dawn; } - if (skycolor.r < 26) - skycolor.r = 26; - else if (skycolor.r > 128) - skycolor.r = 128; + if (skycolor->r < 26) + skycolor->r = 26; + else if (skycolor->r > 128) + skycolor->r = 128; - if (skycolor.b < 26) - skycolor.b = 26; - else if (skycolor.b > 128) - skycolor.b = 128; + if (skycolor->b < 26) + skycolor->b = 26; + else if (skycolor->b > 128) + skycolor->b = 128; - skycolor.g = skycolor.b; + skycolor->g = skycolor->b; } else { - skycolor.b = 128; - skycolor.g = 128; - skycolor.r = 128; + skycolor->b = 128; + skycolor->g = 128; + skycolor->r = 128; } if (gTunnelNum == -1 || @@ -808,20 +805,21 @@ void calc_sky_brightness(void) TunnelSkyFade(); - if (skycolor.r > skyFade) - skycolor.r = skyFade; + if (skycolor->r > skyFade) + skycolor->r = skyFade; - if (skycolor.g > skyFade) - skycolor.g = skyFade; + if (skycolor->g > skyFade) + skycolor->g = skyFade; - if (skycolor.b > skyFade) - skycolor.b = skyFade; + if (skycolor->b > skyFade) + skycolor->b = skyFade; } -#ifdef USE_PGXP +#if USE_PGXP DVECTORF scratchPad_skyVertices[35]; // 1f800044 #else #define scratchPad_skyVertices ((DVECTOR*)getScratchAddr(0x11)) // 1f800044 +static_assert(0x11 + sizeof(DVECTOR) * 35 < 1024 - sizeof(_pct), "scratchpad overflow"); #endif // [D] [T] @@ -833,7 +831,7 @@ void PlotSkyPoly(POLYFT4* polys, int skytexnum, unsigned char r, unsigned char g src = polys; poly = (POLY_FT4*)current->primptr; -#ifdef USE_PGXP +#if USE_PGXP DVECTORF* outpoints = scratchPad_skyVertices; #else DVECTOR* outpoints = scratchPad_skyVertices; @@ -866,7 +864,7 @@ void PlotSkyPoly(POLYFT4* polys, int skytexnum, unsigned char r, unsigned char g addPrim(current->ot + OTSIZE - 1, poly); -#if defined(USE_PGXP) && defined(USE_EXTENDED_PRIM_POINTERS) +#if USE_PGXP && USE_EXTENDED_PRIM_POINTERS poly->pgxp_index = outpoints[src->v0].pgxp_index; #endif @@ -875,11 +873,11 @@ void PlotSkyPoly(POLYFT4* polys, int skytexnum, unsigned char r, unsigned char g } // [D] [T] -void PlotHorizonMDL(MODEL* model, int horizontaboffset) +void PlotHorizonMDL(MODEL* model, int horizontaboffset, RGB16* skycolor) { SVECTOR* verts; -#ifdef USE_PGXP +#if USE_PGXP DVECTORF* dv; #else DVECTOR* dv; @@ -895,7 +893,7 @@ void PlotHorizonMDL(MODEL* model, int horizontaboffset) dv = scratchPad_skyVertices; count = model->num_vertices; -#ifdef USE_PGXP +#if USE_PGXP PGXP_SetZOffsetScale(0.0f, 256.0f); #endif @@ -908,17 +906,17 @@ void PlotHorizonMDL(MODEL* model, int horizontaboffset) if(count == 15) gte_stszotz(&z); -#ifdef USE_PGXP +#if USE_PGXP // store PGXP index // HACK: -1 is needed here for some reason - dv[0].pgxp_index = dv[1].pgxp_index = dv[2].pgxp_index = PGXP_GetIndex() - 1; + dv[0].pgxp_index = dv[1].pgxp_index = dv[2].pgxp_index = PGXP_GetIndex(0) - 1; #endif dv += 3; verts += 3; count -= 3; } while (count); -#ifdef USE_PGXP +#if USE_PGXP PGXP_SetZOffsetScale(0.0f, 1.0f); #endif @@ -929,9 +927,9 @@ void PlotHorizonMDL(MODEL* model, int horizontaboffset) polys = (unsigned char*)model->poly_block; polySize = PolySizes[*polys]; - red = skycolor.r; - green = skycolor.g; - blue = skycolor.b; + red = skycolor->r; + green = skycolor->g; + blue = skycolor->b; // draw sky count = model->num_polys; @@ -957,33 +955,34 @@ void PlotHorizonMDL(MODEL* model, int horizontaboffset) // [D] [T] void DrawSkyDome(void) { + RGB16 skycolor = { 128,128,128 }; VECTOR skyOfs = dummy; - skyOfs.vy = sky_y_offset[GameLevel]; + calc_sky_brightness(&skycolor); + + skyOfs.vy = sky_y_offset[GameLevel]; gte_SetRotMatrix(&inv_camera_matrix); gte_SetTransVector(&skyOfs); - - calc_sky_brightness(); #ifdef PSX // FIXME: use frustrum angle instead? if (((camera_angle.vy - 1450U) & 4095) > 2250) - PlotHorizonMDL(modelpointers[0], HorizonLookup[GameLevel][0]); + PlotHorizonMDL(modelpointers[0], HorizonLookup[GameLevel][0], &skycolor); if (((camera_angle.vy - 651U) & 4095) < 1799) - PlotHorizonMDL(modelpointers[2], HorizonLookup[GameLevel][1]); + PlotHorizonMDL(modelpointers[2], HorizonLookup[GameLevel][1], &skycolor); if (((camera_angle.vy - 1701U) & 4095) < 1749) - PlotHorizonMDL(modelpointers[3], HorizonLookup[GameLevel][2]); + PlotHorizonMDL(modelpointers[3], HorizonLookup[GameLevel][2], &skycolor); if (((camera_angle.vy - 400U) & 4095) > 2300) - PlotHorizonMDL(modelpointers[1], HorizonLookup[GameLevel][3]); + PlotHorizonMDL(modelpointers[1], HorizonLookup[GameLevel][3], &skycolor); #else // draw full sky - no need in frustrum culling - PlotHorizonMDL(modelpointers[0], HorizonLookup[GameLevel][0]); - PlotHorizonMDL(modelpointers[2], HorizonLookup[GameLevel][1]); - PlotHorizonMDL(modelpointers[3], HorizonLookup[GameLevel][2]); - PlotHorizonMDL(modelpointers[1], HorizonLookup[GameLevel][3]); + PlotHorizonMDL(modelpointers[0], HorizonLookup[GameLevel][0], &skycolor); + PlotHorizonMDL(modelpointers[2], HorizonLookup[GameLevel][1], &skycolor); + PlotHorizonMDL(modelpointers[3], HorizonLookup[GameLevel][2], &skycolor); + PlotHorizonMDL(modelpointers[1], HorizonLookup[GameLevel][3], &skycolor); #endif } diff --git a/src_rebuild/Game/C/sound.c b/src_rebuild/Game/C/sound.c index c1e5b641e..42724cb85 100644 --- a/src_rebuild/Game/C/sound.c +++ b/src_rebuild/Game/C/sound.c @@ -52,6 +52,7 @@ int gMasterVolume = 0; int gMusicVolume = -4000; int Song_ID = -1; +int Song_SetPos = -1; int VABID = -1; int gSoundMode = 1; // mono or stereo @@ -67,6 +68,7 @@ int vblcounter = 0; // vblank counter // [D] [T] void SoundHandler(void) { + CHANNEL_DATA* c; int ct; int off; @@ -77,11 +79,16 @@ void SoundHandler(void) for (ct = 0; ct < MAX_SFX_CHANNELS; ct++) { - if (channels[ct].loop || channels[ct].time == 0) + c = &channels[ct]; + if ((c->flags & CHAN_LOOP) || c->time == 0) + { continue; + } - if (--channels[ct].time == 0) + if (--c->time == 0) + { off |= SPU_KEYCH(ct); + } } if (off) @@ -94,7 +101,15 @@ void VsyncProc(void) vblcounter++; if (Song_ID != -1) + { + if (Song_SetPos != -1) + { + XM_SetSongPos(Song_ID, Song_SetPos); + Song_SetPos = -1; + } + XM_Update(); + } SoundHandler(); } @@ -140,8 +155,7 @@ void ClearChannelFields(int channel) chan = &channels[channel]; - chan->loop = 0; - chan->locked = 0; + chan->flags = 0; chan->time = 0; chan->samplerate = 0; chan->srcvolume = -10000; @@ -320,9 +334,6 @@ int CalculateVolume(int channel) return volume - 10000; } - -int gSurround = 0; - // [D] [T] void UpdateVolumeAttributesS(int channel, int proximity) { @@ -352,7 +363,7 @@ void UpdateVolumeAttributesS(int channel, int proximity) vol = (vol + vol / 2 + vol / 8 + vol / 128) * master_volume / 16384; chan->attr.volume.left = vol; - chan->attr.volume.right = gSurround ? -vol : vol; // HMM: why like that? + chan->attr.volume.right = vol; if (vol == 0) return; @@ -426,7 +437,7 @@ void UpdateVolumeAttributesS(int channel, int proximity) if (proximity > 0) damp = damp * dist / 12000; - chan->attr.volume.right = gSurround ? -MAX(0, vol - damp) : MAX(0, vol - damp); + chan->attr.volume.right = MAX(0, vol - damp); } } @@ -455,45 +466,52 @@ int CompleteSoundSetup(int channel, int bank, int sample, int pitch, int proximi int bpf; int rate; CHANNEL_DATA* chan; + SAMPLE_DATA* samp; - rate = samples[bank][sample].samplerate * pitch; + samp = &samples[bank][sample]; + + rate = samp->samplerate * pitch; +#ifdef PAL_VERSION bpf = (rate / 4096) / 50; +#else + bpf = (rate / 4096) / 60; +#endif if (bpf == 0) { - channel = -1; + return -1; } - else - { - chan = &channels[channel]; - - if (gSoundMode == 1 && proximity != -1) - UpdateVolumeAttributesS(channel, proximity); - else - UpdateVolumeAttributesM(channel); - stop_sound_handler = 1; + chan = &channels[channel]; + + if (gSoundMode == 1 && proximity != -1) + UpdateVolumeAttributesS(channel, proximity); + else + UpdateVolumeAttributesM(channel); - chan->attr.mask = SPU_VOICE_VOLL | SPU_VOICE_VOLR | SPU_VOICE_VOLMODEL | SPU_VOICE_VOLMODER | SPU_VOICE_PITCH | SPU_VOICE_WDSA; - chan->attr.addr = samples[bank][sample].address; - chan->attr.pitch = MIN(rate / 44100, 16383); - chan->time = (samples[bank][sample].length / bpf) * 2 + 2; - chan->loop = samples[bank][sample].loop; + stop_sound_handler = 1; - chan->samplerate = samples[bank][sample].samplerate; + chan->attr.mask = SPU_VOICE_VOLL | SPU_VOICE_VOLR | SPU_VOICE_VOLMODEL | SPU_VOICE_VOLMODER | SPU_VOICE_PITCH | SPU_VOICE_WDSA; + chan->attr.addr = samp->address; + chan->attr.pitch = MIN(rate / 44100, 16383); + chan->time = (samp->length / bpf) * 2 + 2; - if (sound_paused != 0) - { - chan->attr.volume.left = 0; - chan->attr.volume.right = 0; - } + chan->flags &= ~CHAN_LOOP; + chan->flags |= samp->loop ? CHAN_LOOP : 0; - SpuSetVoiceAttr(&chan->attr); - SpuSetKey(1, chan->attr.voice); + chan->samplerate = samp->samplerate; - stop_sound_handler = 0; + if (sound_paused != 0) + { + chan->attr.volume.left = 0; + chan->attr.volume.right = 0; } + SpuSetVoiceAttr(&chan->attr); + SpuSetKey(1, chan->attr.voice); + + stop_sound_handler = 0; + return channel; } @@ -505,7 +523,7 @@ void ComputeDoppler(CHANNEL_DATA *ch) int seperationrate; VECTOR *srcPos; - long* srcVel; // LONGVECTOR3 + int* srcVel; // LONGVECTOR3 PLAYER *pl; int dx, dy, dz; @@ -518,7 +536,7 @@ void ComputeDoppler(CHANNEL_DATA *ch) return; } - srcVel = (long*)ch->srcvelocity; + srcVel = (int*)ch->srcvelocity; pl = &player[ch->player]; @@ -528,9 +546,9 @@ void ComputeDoppler(CHANNEL_DATA *ch) dist = jsqrt(dx * dx + dy * dy + dz * dz); - dx = (srcPos->vx - pl->cameraPos.vx) + FIXEDH(srcVel[0] - pl->camera_vel[0]); - dy = (srcPos->vy + pl->cameraPos.vy) + FIXEDH(srcVel[1] - pl->camera_vel[1]); - dz = (srcPos->vz - pl->cameraPos.vz) + FIXEDH(srcVel[2] - pl->camera_vel[2]); + dx += FIXEDH(srcVel[0] - pl->camera_vel[0]); + dy += FIXEDH(srcVel[1] - pl->camera_vel[1]); + dz += FIXEDH(srcVel[2] - pl->camera_vel[2]); seperationrate = jsqrt(dx * dx + dy * dy + dz * dz); @@ -577,6 +595,9 @@ int Start3DTrackingSound(int channel, int bank, int sample, VECTOR *position, LO channel = CompleteSoundSetup(channel, bank, sample, 4096, 0); + if (channel < 0) + return -1; + ComputeDoppler(&channels[channel]); SetChannelPitch(channel, 4096); @@ -605,6 +626,9 @@ int Start3DSoundVolPitch(int channel, int bank, int sample, int x, int y, int z, channel = CompleteSoundSetup(channel, bank, sample, pitch, 0); + if (channel < 0) + return -1; + ComputeDoppler(&channels[channel]); SetChannelPitch(channel, pitch); @@ -848,29 +872,34 @@ void UnPauseSound(void) // [D] [T] void StopChannel(int channel) { + CHANNEL_DATA* c; u_char lock; int vsync; if (channel < 0 || channel >= MAX_SFX_CHANNELS) return; - lock = channels[channel].locked; + c = &channels[channel]; + vsync = VSync(-1); - SpuSetKey(0, channels[channel].attr.voice); + SpuSetKey(0, c->attr.voice); // PSX SPU keyoff sometimes does not work for first time due to it's nature do { - if (SpuGetKeyStatus(channels[channel].attr.voice) == 0) + if (SpuGetKeyStatus(c->attr.voice) == 0) break; #ifdef __EMSCRIPTEN__ emscripten_sleep(0); #endif } while (VSync(-1) - vsync < 8); + // save lock status + lock = c->flags & CHAN_LOCKED; + ClearChannelFields(channel); - channels[channel].locked = lock; + c->flags = lock; } // [D] [T] @@ -891,7 +920,7 @@ void LockChannel(int channel) if (channel < 0 || channel >= MAX_SFX_CHANNELS) // [A] return; - channels[channel].locked = 1; + channels[channel].flags |= CHAN_LOCKED; } // [D] [T] @@ -900,7 +929,7 @@ void UnlockChannel(int c) if (c < 0 || c >= MAX_SFX_CHANNELS) // [A] return; - channels[c].locked = 0; + channels[c].flags &= ~CHAN_LOCKED; } // [D] [T] @@ -923,7 +952,7 @@ int LoadSoundBank(char *address, int length, int bank) SpuSetTransferMode(SPU_TRANSFER_BY_DMA); SpuSetTransferStartAddr(spuaddress); - SpuWrite((unsigned char*)address + slength, length - slength); + SpuWrite((u_char*)address + slength, length - slength); SpuIsTransferCompleted(SPU_TRANSFER_WAIT); @@ -1001,7 +1030,7 @@ int LoadSoundBankDynamic(char *address, int length, int dbank) SpuSetTransferMode(SPU_TRANSFER_BY_DMA); SpuSetTransferStartAddr(lsbTabs.addr); - SpuWrite((unsigned char*)address + slength, length - slength); + SpuWrite((u_char*)address + slength, length - slength); SpuIsTransferCompleted(SPU_TRANSFER_WAIT); @@ -1057,6 +1086,7 @@ void StopXM(void) // [D] [T] int GetFreeChannel(int force) { + CHANNEL_DATA* c; int channel; int it; int least; @@ -1068,7 +1098,7 @@ int GetFreeChannel(int force) channel = 0; // find free channel - while (channel < MAX_SFX_CHANNELS && (channels[channel].locked || status[channel] != SPU_OFF && status[channel] != SPU_RESET)) + while (channel < MAX_SFX_CHANNELS && ((channels[channel].flags & CHAN_LOCKED) || status[channel] != SPU_OFF && status[channel] != SPU_RESET)) { channel++; } @@ -1083,15 +1113,16 @@ int GetFreeChannel(int force) channel = -1; least = 0; - for (it = 0; it < MAX_SFX_CHANNELS; it++) + c = &channels[0]; + for (it = 0; it < MAX_SFX_CHANNELS; it++, c++) { - if (channels[it].locked || channels[it].loop) + if (c->flags & (CHAN_LOCKED | CHAN_LOOP)) continue; - if (channel == -1 || channels[it].time < least) + if (channel == -1 || c->time < least) { channel = it; - least = channels[it].time; + least = c->time; } } @@ -1102,7 +1133,7 @@ int GetFreeChannel(int force) } // [D] [T] -void AllocateReverb(long mode, long depth) +void AllocateReverb(int mode, int depth) { SpuReverbAttr r_attr; diff --git a/src_rebuild/Game/C/sound.h b/src_rebuild/Game/C/sound.h index 01d96e382..ee22c2750 100644 --- a/src_rebuild/Game/C/sound.h +++ b/src_rebuild/Game/C/sound.h @@ -1,28 +1,31 @@ #ifndef SOUND_H #define SOUND_H +enum ChanFlags +{ + CHAN_LOOP = (1 << 0), + CHAN_LOCKED = (1 << 1) +}; + struct CHANNEL_DATA { SpuVoiceAttr attr; - - u_char loop; - u_char locked; - u_short time; + VECTOR* srcposition; + VECTOR position; + LONGVECTOR3* srcvelocity; int samplerate; - char player; int srcvolume; int volumeScale; + int cameradist; + int lastcameradist; u_short srcpitch; u_short dopplerScale; - int cameradist; - int lastcameradist; - - VECTOR* srcposition; - VECTOR position; - LONGVECTOR3* srcvelocity; + u_short time; + u_char flags; + char player; }; extern CHANNEL_DATA channels[16]; @@ -32,13 +35,14 @@ extern int gMusicVolume; extern int gSoundMode; extern int Song_ID; +extern int Song_SetPos; extern int VABID; extern int music_paused; extern void InitSound(); // 0x000790E4 extern void ResetSound(); // 0x00079250 -extern void AllocateReverb(long mode, long depth); // 0x0007AB3C +extern void AllocateReverb(int mode, int depth); // 0x0007AB3C extern void SetReverbState(int on); // 0x0007A6C0 extern void SetReverbInGameState(int on); // 0x0007A704 extern int SetReverbChannelState(int ch, int on); // 0x0007A75C diff --git a/src_rebuild/Game/C/spool.c b/src_rebuild/Game/C/spool.c index 6eec9cddf..02f81b5c8 100644 --- a/src_rebuild/Game/C/spool.c +++ b/src_rebuild/Game/C/spool.c @@ -24,6 +24,13 @@ #include "camera.h" #include "dr2roads.h" +#define SPOOL_REGION 0 +#define SPOOL_TPAGE 1 +#define SPOOL_SOUNDBANK 2 +#define SPOOL_MISC 3 + +typedef void(*spooledFuncPtr)(); + struct SPOOLQ { u_char type; @@ -73,12 +80,14 @@ int SpecialByRegion[4][20] = { {2, 5, 4, 1, 2, 1, 4, 3, 2, 2, 2, 2, 3, 3, 3, 0, 0, 0, 0, 0}, }; +SPOOLQ spooldata[48]; + char* model_spool_buffer = NULL; int cell_objects_add[5]; int cell_slots_add[5]; - -typedef void(*spooledFuncPtr)(); +short loading_region[4]; +int regions_unpacked[4]; SXYPAIR* Music_And_AmbientOffsets; @@ -89,28 +98,19 @@ int NumAreas; char* RegionSpoolInfo; unsigned short *spoolinfo_offsets; -char* specmallocptr; -char *specLoadBuffer; - int doSpooling = 1; -short loading_region[4]; -int regions_unpacked[4]; - int spool_regioncounter; int spoolerror; // UNUSED int spool_regionpos; +int spoolcounter; volatile int spoolactive; // volatile is required at least for PC volatile int quickSpool; -int models_ready; - -short specspooldata[3] = { 20, 10, 4 }; +int models_ready; int tsetcounter; int tsetpos; -int spoolcounter; - int loadbank_read; int loadbank_write; @@ -118,12 +118,6 @@ volatile int spoolpos; volatile int spoolpos_reading; volatile int spoolpos_writing; -int allowSpecSpooling; -int startSpecSpool; - -int unpack_roadmap_flag; -int unpack_cellptr_flag; - char *packed_cell_pointers; SPL_REGIONINFO spool_regioninfo[8]; @@ -140,8 +134,6 @@ static volatile int current_sector; static volatile int switch_spooltype; static volatile int endchunk; -int send_bank; -int sample_chunk; volatile int chunk_complete; @@ -151,7 +143,12 @@ int new_area_location; int LoadingArea = 0; unsigned short *newmodels = NULL; -SPOOLQ spooldata[48]; +#define CHECK_SWITCHSPOOL() \ + if (switch_spooltype) \ + { \ + changemode(&spooldata[spoolpos_writing]); \ + return; \ + } \ // configure spooler #if USE_PC_FILESYSTEM @@ -450,9 +447,7 @@ void InitSpooling(void) spoolcounter = 0; loadbank_read = 0; spoolpos = 0; - unpack_roadmap_flag = 0; loadbank_write = 0; - unpack_cellptr_flag = 0; } int tsetinfo[32]; @@ -476,6 +471,7 @@ void SendTPage(void) if (nTPchunks == 0) { + // Send palettes if (slot != tpageloaded[tpage2send] - 1) { npalettes = *(int *)(model_spool_buffer + 0xE000); @@ -492,7 +488,7 @@ void SendTPage(void) cluts.h = npalettes / 4 + 1; - LoadImage(&cluts, (u_long *)(model_spool_buffer + 0xE000 + 4)); + LoadImage(&cluts, (u_long*)(model_spool_buffer + 0xE000 + 4)); clutptr = (u_int*)(texture_cluts[tpage2send]); i = 0; @@ -516,7 +512,7 @@ void SendTPage(void) { if (slot != tpageloaded[tpage2send] - 1) { - LoadImage(&tpage, (u_long *)(model_spool_buffer + 0xA000 + (loadbank_write % 2) * 256 * 32)); + LoadImage(&tpage, (u_long*)(model_spool_buffer + 0xA000 + (loadbank_write & 1) * 256 * 32)); tpage.y = tpage.y + tpage.h; } @@ -619,7 +615,7 @@ void LoadInAreaTSets(int area) tsetinfo[tsetcounter * 2 + 1] = availableslots[slot]; tsetinfo[tsetcounter * 2] = tpages[i]; - RequestSpool(1, 0, offset, 17, loadaddr, SendTPage); + RequestSpool(SPOOL_TPAGE, 0, offset, 17, loadaddr, SendTPage); offset += 17; tsetcounter++; @@ -658,11 +654,16 @@ void init_spooled_models(void) size = *(int *)addr; model = (MODEL *)(addr + 4); + modelpointers[model_number] = model; + pLodModels[model_number] = model; + lod = Low2LowerDetailTable[model_number]; if (lod != 0xffff && lod != model_number) pLodModels[model_number] = modelpointers[lod]; + ProcessModel(model_number); + if (model->instance_number == -1) { if ((uint)model->collision_block != 0) @@ -689,10 +690,6 @@ void init_spooled_models(void) } model->poly_block += (int)model; - - modelpointers[model_number] = model; - pLodModels[model_number] = model; - addr += size + 4; } @@ -714,6 +711,7 @@ void CheckValidSpoolData(void) if (models_ready) init_spooled_models(); +#ifdef PSX if (spoolactive && check_regions_present()) { stopgame(); @@ -726,6 +724,7 @@ void CheckValidSpoolData(void) startgame(); } +#endif // PSX } // [D] [T] @@ -741,7 +740,7 @@ void LoadInAreaModels(int area) int length = AreaData[area].model_size; newmodels = (ushort *)(model_spool_buffer + (length-1) * 2048); - RequestSpool(3, 0, AreaData[area].model_offset, length, model_spool_buffer, SetupModels); + RequestSpool(SPOOL_MISC, 0, AreaData[area].model_offset, length, model_spool_buffer, SetupModels); } // [D] [T] @@ -758,14 +757,6 @@ void CheckLoadAreaData(int cellx, int cellz) spoolptr = (Spool *)(RegionSpoolInfo + spoolinfo_offsets[current_region]); -#ifndef PSX - // [A] this fixes spooling not activated bug (reversing bug?) - if (LoadedArea != spoolptr->super_region && spoolptr->super_region != 0xFF && old_region != -1) - { - LoadedArea = spoolptr->super_region; - } - else -#endif if (old_region == -1 && spoolptr->super_region != 0xFF) { // just load the area if no @@ -777,7 +768,7 @@ void CheckLoadAreaData(int cellx, int cellz) if (old_region == -1) LoadedArea = -1; - else if (/*spoolptr->super_region == 0xFF ||*/ nAreas == 0) + else if (spoolptr->super_region == 0xFF && nAreas == 0) return; #define BOUNDARY_MIN 15 @@ -852,7 +843,7 @@ void ClearRegion(int target_region) ClearMem(PVS_Buffers[target_region]-4, pvsSize[target_region]); - RoadMapDataRegions[target_region] = (short*)PVS_Buffers[0]; + RoadMapDataRegions[target_region] = (short*)PVS_Buffers[target_region]; } inline int _getIntAdv(char** ptr) @@ -998,134 +989,131 @@ void changemode(SPOOLQ *current); // [D] [T] void data_cb_textures(void) { - if (chunk_complete) - { - chunk_complete = 0; - nTPchunks = nTPchunks_writing; + if (chunk_complete == 0) + return; - SendTPage(); + chunk_complete = 0; + nTPchunks = nTPchunks_writing; - if (nTPchunks != 0) - loadbank_write++; + SendTPage(); - nTPchunks_writing++; + if (nTPchunks != 0) + loadbank_write++; - if (nTPchunks_writing == 5) - { - nTPchunks_writing = 0; - spoolpos_writing++; + nTPchunks_writing++; - if (ntpages == 0) - { - if (!switch_spooltype) - { - CdDataCallback(NULL); - - if (spoolpos_writing == spoolcounter) - { - SPOOL_WARNING("All SPOOL requests (%d) completed successfully on TEXTURES\n", spoolcounter); // [A] - - spoolcounter = 0; - spoolpos_writing = 0; - spoolpos_reading = 0; - spoolactive = 0; - } - else - { - UpdateSpool(); - } - } - else - { - changemode(&spooldata[spoolpos_writing]); - } - } - } + if (nTPchunks_writing != 5) + return; + + nTPchunks_writing = 0; + spoolpos_writing++; + + if (ntpages != 0) + return; + + CHECK_SWITCHSPOOL(); + + CdDataCallback(NULL); + + if (spoolpos_writing == spoolcounter) + { + SPOOL_WARNING("All SPOOL requests (%d) completed successfully on TEXTURES\n", spoolcounter); // [A] + + spoolcounter = 0; + spoolpos_writing = 0; + spoolpos_reading = 0; + spoolactive = 0; + } + else + { + UpdateSpool(); } } // [D] [T] void ready_cb_textures(unsigned char intr, unsigned char *result) { - if (intr == 1) + if (intr != 1) { - CdGetSector(target_address, SECTOR_SIZE); + FoundError("ready_cb_textures", intr, result); + return; + } - target_address += CDSECTOR_SIZE; - sectors_this_chunk--; - current_sector++; - sectors_to_read--; + CdGetSector(target_address, SECTOR_SIZE); - if (sectors_this_chunk == 0) - { - if (nTPchunks_reading) - loadbank_read++; + target_address += CDSECTOR_SIZE; + sectors_this_chunk--; + current_sector++; + sectors_to_read--; - nTPchunks_reading++; - chunk_complete = intr; + if (sectors_this_chunk != 0) + return; - if (sectors_to_read == 0) - { - ntpages--; + if (nTPchunks_reading) + loadbank_read++; - if (ntpages == 0) - { - spoolpos_reading++; - test_changemode(); - } - else - { - nTPchunks_reading = 0; - sectors_to_read = 17; + nTPchunks_reading++; + chunk_complete = intr; - target_address = spooldata[spoolpos_reading].addr + 0x4000; - spoolpos_reading++; + if (sectors_to_read == 0) + { + ntpages--; - sectors_this_chunk = intr; - } - } - else - { - sectors_this_chunk = 4; - target_address = spooldata[spoolpos_reading].addr + (loadbank_read & 1U) * 0x2000; - } + if (ntpages == 0) + { + spoolpos_reading++; + test_changemode(); + } + else + { + nTPchunks_reading = 0; + sectors_to_read = 17; + + target_address = spooldata[spoolpos_reading].addr + 0x4000; + spoolpos_reading++; + + sectors_this_chunk = intr; } } else - FoundError("ready_cb_textures", intr, result); + { + sectors_this_chunk = 4; + target_address = spooldata[spoolpos_reading].addr + (loadbank_read & 1U) * 0x2000; + } } // [D] [T] void ready_cb_regions(unsigned char intr, unsigned char *result) { - if (intr == 1) + if (intr != 1) { - CdGetSector(target_address, SECTOR_SIZE); + FoundError("ready_cb_regions", intr, result); + return; + } - target_address += CDSECTOR_SIZE; - sectors_this_chunk--; - current_sector++; - sectors_to_read--; + CdGetSector(target_address, SECTOR_SIZE); - if (sectors_this_chunk == 0) - { - spoolpos_reading++; - chunk_complete = intr; + target_address += CDSECTOR_SIZE; + sectors_this_chunk--; + current_sector++; + sectors_to_read--; - if (sectors_to_read == 0) - { - endchunk = intr; - test_changemode(); - } - else - { - target_address = spooldata[spoolpos_reading].addr; - sectors_this_chunk = spooldata[spoolpos_reading].nsectors; - } + if (sectors_this_chunk == 0) + { + spoolpos_reading++; + chunk_complete = intr; + + if (sectors_to_read == 0) + { + endchunk = intr; + test_changemode(); + } + else + { + target_address = spooldata[spoolpos_reading].addr; + sectors_this_chunk = spooldata[spoolpos_reading].nsectors; } } - else - FoundError("ready_cb_regions", intr, result); } // [D] [T] @@ -1133,40 +1121,35 @@ void data_cb_regions(void) { SPOOLQ* current = &spooldata[spoolpos_writing]; - if (chunk_complete) - { - chunk_complete = 0; + if (chunk_complete == 0) + return; - if (current->func != NULL) - (current->func)(); + chunk_complete = 0; - spoolpos_writing++; + if (current->func != NULL) + (current->func)(); - if (endchunk) - { - if (!switch_spooltype) - { - CdDataCallback(NULL); + spoolpos_writing++; - if (spoolpos_writing == spoolcounter) - { - SPOOL_WARNING("All SPOOL requests (%d) completed successfully on REGIONS\n", spoolcounter); // [A] + if (endchunk == 0) + return; - spoolcounter = 0; - spoolpos_writing = 0; - spoolpos_reading = 0; - spoolactive = 0; - } - else - { - UpdateSpool(); - } - } - else - { - changemode(&spooldata[spoolpos_writing]); - } - } + CHECK_SWITCHSPOOL(); + + CdDataCallback(NULL); + + if (spoolpos_writing == spoolcounter) + { + SPOOL_WARNING("All SPOOL requests (%d) completed successfully on REGIONS\n", spoolcounter); // [A] + + spoolcounter = 0; + spoolpos_writing = 0; + spoolpos_reading = 0; + spoolactive = 0; + } + else + { + UpdateSpool(); } } @@ -1176,37 +1159,32 @@ void data_cb_misc(void) { SPOOLQ *current = &spooldata[spoolpos_writing]; - if (chunk_complete) - { - chunk_complete = 0; + if (chunk_complete == 0) + return; - if (current->func != NULL) - (*current->func)(); + chunk_complete = 0; - spoolpos_writing++; + if (current->func != NULL) + (*current->func)(); - if (!switch_spooltype) - { - CdDataCallback(NULL); + spoolpos_writing++; + + CHECK_SWITCHSPOOL(); + + CdDataCallback(NULL); - if (spoolpos_writing == spoolcounter) - { - SPOOL_WARNING("All SPOOL requests (%d) completed successfully on MISC\n", spoolcounter); // [A] + if (spoolpos_writing == spoolcounter) + { + SPOOL_WARNING("All SPOOL requests (%d) completed successfully on MISC\n", spoolcounter); // [A] - spoolcounter = 0; - spoolpos_writing = 0; - spoolpos_reading = 0; - spoolactive = 0; - } - else - { - UpdateSpool(); - } - } - else - { - changemode(&spooldata[spoolpos_writing]); - } + spoolcounter = 0; + spoolpos_writing = 0; + spoolpos_reading = 0; + spoolactive = 0; + } + else + { + UpdateSpool(); } } @@ -1348,7 +1326,6 @@ void unpack_cellpointers(int region_to_unpack, int target_barrel_region, char* c int packtype; - unpack_cellptr_flag = 0; packtype = *(int *)(cell_addr + 4); source_packed_data = (ushort *)(cell_addr + 8); @@ -1406,8 +1383,6 @@ void unpack_cellpointers(int region_to_unpack, int target_barrel_region, char* c printError("BAD PACKED CELL POINTER DATA, region = %d, packtype = %d\n", region_to_unpack, packtype); D_CHECK_ERROR(true, "Bad cell pointer data"); - - unpack_cellptr_flag = 0; } } @@ -1505,7 +1480,6 @@ int UpdateSpoolPC(void) break; case 1: // textures - // read cluts nTPchunks = 0; SPL_READ(current->addr + CDSECTOR_SIZE * 2 * 4, 1); @@ -1516,9 +1490,10 @@ int UpdateSpoolPC(void) // read tpage (4 sectors 4 times = 16) for (int i = 0; i < 4; i++) { - SPL_READ(current->addr + (loadbank_write & 1U) * 256 * 32, 4); + SPL_READ(current->addr + (loadbank_write & 1) * 256 * 32, 4); SendTPage(); + loadbank_write++; nTPchunks++; } @@ -1618,31 +1593,31 @@ int LoadRegionData(int region, int target_region) #ifndef PSX if (gDemoLevel) { - RequestSpool(0, 0, offset, spoolptr->roadm_size, PVS_Buffers[target_region], NULL); + RequestSpool(SPOOL_REGION, 0, offset, spoolptr->roadm_size, PVS_Buffers[target_region], NULL); offset += spoolptr->roadm_size; - RequestSpool(0, 0, offset, spoolptr->cell_data_size[1], cell_buffer, NULL); + RequestSpool(SPOOL_REGION, 0, offset, spoolptr->cell_data_size[1], cell_buffer, NULL); offset += spoolptr->cell_data_size[1]; - RequestSpool(0, 0, offset, spoolptr->cell_data_size[0], (char *)(cells + cell_slots_add[target_region]), NULL); + RequestSpool(SPOOL_REGION, 0, offset, spoolptr->cell_data_size[0], (char *)(cells + cell_slots_add[target_region]), NULL); offset += spoolptr->cell_data_size[0]; - RequestSpool(0, 0, offset, spoolptr->cell_data_size[2], (char *)(cell_objects + num_straddlers + cell_objects_add[target_region]), GotRegion); + RequestSpool(SPOOL_REGION, 0, offset, spoolptr->cell_data_size[2], (char *)(cell_objects + num_straddlers + cell_objects_add[target_region]), GotRegion); offset += spoolptr->cell_data_size[2]; } else #endif { - RequestSpool(0, 0, offset, spoolptr->cell_data_size[1], cell_buffer, NULL); + RequestSpool(SPOOL_REGION, 0, offset, spoolptr->cell_data_size[1], cell_buffer, NULL); offset += spoolptr->cell_data_size[1]; - RequestSpool(0, 0, offset, spoolptr->cell_data_size[0], (char *)(cells + cell_slots_add[target_region]), NULL); + RequestSpool(SPOOL_REGION, 0, offset, spoolptr->cell_data_size[0], (char *)(cells + cell_slots_add[target_region]), NULL); offset += spoolptr->cell_data_size[0]; - RequestSpool(0, 0, offset, spoolptr->cell_data_size[2], (char *)(cell_objects + num_straddlers + cell_objects_add[target_region]), NULL); + RequestSpool(SPOOL_REGION, 0, offset, spoolptr->cell_data_size[2], (char *)(cell_objects + num_straddlers + cell_objects_add[target_region]), NULL); offset += spoolptr->cell_data_size[2]; - RequestSpool(0, 0, offset, spoolptr->roadm_size, PVS_Buffers[target_region] - 4, GotRegion); + RequestSpool(SPOOL_REGION, 0, offset, spoolptr->roadm_size, PVS_Buffers[target_region] - 4, GotRegion); offset += spoolptr->roadm_size; } @@ -1675,6 +1650,45 @@ void UnpackRegion(int region_to_unpack, int target_barrel_region) //--------------------------------------------------------------------- +// Special car spooling + +enum SpecialSpoolState +{ + SpecSpool_None = 0, + + SpecSpool_Tpage1, + SpecSpool_Tpage2, + SpecSpool_Cluts, + SpecSpool_Cosmetics, + + SpecSpool_CleanSpool, + SpecSpool_LowSpool, + + SpecSpool_CleanModel, + SpecSpool_DamagedModel, + SpecSpool_LowModel +}; + +int specialState = SpecSpool_None; + +int allowSpecSpooling; +int startSpecSpool; +char* specmallocptr; +char* specLoadBuffer; +short specSpoolModelIndex = 4; + +int* modelMemory; + +int lengthLowBlock; +int lastCleanBlock; +int lengthDamBlock; + +int firstLowBlock; +int firstDamBlock; + +int specBlocksToLoad = 0; +char specModelValid = 1; +int specSpoolComplete; void SpecialStartNextBlock(void); @@ -1694,7 +1708,7 @@ void SpecClutsSpooled(void) for (int i = 0; i < 2; i++) { int index = specialSlot + i; - int tpage = specTpages[GameLevel][(specspooldata[2]-1) * 2 + i]; + int tpage = specTpages[GameLevel][(specSpoolModelIndex-1) * 2 + i]; carTpages[GameLevel][i + 6] = tpageslots[index] = tpage; tpageloaded[tpage] = specialSlot + i + 1; @@ -1721,38 +1735,19 @@ void SpecClutsSpooled(void) } #endif } - - if (quickSpool != 1) - DrawSyncCallback(SpecialStartNextBlock); } -int *modelMemory; - -int lengthLowBlock; -int lastCleanBlock; -int lengthDamBlock; - -int firstLowBlock; -int firstDamBlock; - -int specBlocksToLoad = 0; -int specialState = 0; -char specModelValid = 1; -int specSpoolComplete; - // [D] [T] void CleanModelSpooled(void) { - int *loadaddr; - int *mem; + int* loadaddr; + int* polyBlock; loadaddr = (int *)specLoadBuffer; if (specBlocksToLoad == lastCleanBlock-1) { loadaddr = (int *)(specLoadBuffer + 12); - - modelMemory = (int *)specmallocptr; gCarCleanModelPtr[4] = (MODEL *)modelMemory; } @@ -1760,20 +1755,12 @@ void CleanModelSpooled(void) while (loadaddr < (int*)(specLoadBuffer + CDSECTOR_SIZE)) *modelMemory++ = *loadaddr++; - mem = (int*)((int)gCarCleanModelPtr[4] + gCarCleanModelPtr[4]->poly_block); // [A] pls check, might be invalid + polyBlock = (int*)((int)gCarCleanModelPtr[4] + gCarCleanModelPtr[4]->poly_block); // [A] pls check, might be invalid - if (specBlocksToLoad == 0 || mem < modelMemory) - { -#if USE_PC_FILESYSTEM - if (gContentOverride) - { - // [A] vertices - LoadCarModelFromFile((char*)gCarCleanModelPtr[4], MissionHeader->residentModels[4], CAR_MODEL_CLEAN); - } -#endif - + if (specBlocksToLoad == 0 || modelMemory > polyBlock) + { specBlocksToLoad = 0; - modelMemory = mem; + modelMemory = polyBlock; gCarCleanModelPtr[4]->vertices += (int)gCarCleanModelPtr[4]; gCarCleanModelPtr[4]->normals += (int)gCarCleanModelPtr[4]; @@ -1793,15 +1780,14 @@ int damOffset; // [D] [T] void DamagedModelSpooled(void) { - int *loadaddr; - int *mem; + int* loadaddr; + int* polyBlock; loadaddr = (int *)specLoadBuffer; if (specBlocksToLoad == lengthDamBlock-1) { loadaddr = (int *)(specLoadBuffer + damOffset); - gCarDamModelPtr[4] = (MODEL *)modelMemory; } @@ -1809,20 +1795,12 @@ void DamagedModelSpooled(void) while (loadaddr < (int*)(specLoadBuffer + CDSECTOR_SIZE)) *modelMemory++ = *loadaddr++; - mem = (int*)((int)gCarDamModelPtr[4] + gCarDamModelPtr[4]->poly_block); // [A] pls check, might be invalid + polyBlock = (int*)((int)gCarDamModelPtr[4] + gCarDamModelPtr[4]->poly_block); // [A] pls check, might be invalid - if (specBlocksToLoad == 0 || mem < modelMemory) - { -#if USE_PC_FILESYSTEM - if (gContentOverride) - { - // [A] vertices - LoadCarModelFromFile((char*)gCarDamModelPtr[4], MissionHeader->residentModels[4], CAR_MODEL_DAMAGED); - } -#endif - + if (specBlocksToLoad == 0 || modelMemory > polyBlock) + { specBlocksToLoad = 0; - modelMemory = mem; + modelMemory = polyBlock; gCarDamModelPtr[4]->vertices += (int)gCarDamModelPtr[4]; gCarDamModelPtr[4]->normals += (int)gCarDamModelPtr[4]; @@ -1832,7 +1810,6 @@ void DamagedModelSpooled(void) if (quickSpool != 1) DrawSyncCallback(SpecialStartNextBlock); - } int lowOffset; @@ -1840,15 +1817,14 @@ int lowOffset; // [D] [T] void LowModelSpooled(void) { - int *loadaddr; - int *mem; + int* loadaddr; + int* polyBlock; loadaddr = (int *)specLoadBuffer; if (specBlocksToLoad == lengthLowBlock - 1) { loadaddr = (int *)(specLoadBuffer + lowOffset); - gCarLowModelPtr[4] = (MODEL *)modelMemory; } @@ -1856,20 +1832,12 @@ void LowModelSpooled(void) while (loadaddr < (int*)(specLoadBuffer + CDSECTOR_SIZE)) *modelMemory++ = *loadaddr++; - mem = (int*)((int)gCarLowModelPtr[4] + gCarLowModelPtr[4]->poly_block); // [A] pls check, might be invalid + polyBlock = (int*)((int)gCarLowModelPtr[4] + gCarLowModelPtr[4]->poly_block); // [A] pls check, might be invalid - if (specBlocksToLoad == 0 || mem < modelMemory) + if (specBlocksToLoad == 0 || modelMemory > polyBlock) { -#if USE_PC_FILESYSTEM - if (gContentOverride) - { - // [A] vertices - LoadCarModelFromFile((char*)gCarLowModelPtr[4], MissionHeader->residentModels[4], CAR_MODEL_LOWDETAIL); - } -#endif - specBlocksToLoad = 0; - modelMemory = mem; + modelMemory = polyBlock; gCarLowModelPtr[4]->vertices += (int)gCarLowModelPtr[4]; gCarLowModelPtr[4]->normals += (int)gCarLowModelPtr[4]; @@ -1890,56 +1858,100 @@ void CleanSpooled(void) { MODEL *model; + // first block is model sizes if (specBlocksToLoad == 6) { + int lastDamBlock; + int lastLowBlock; + // [A] for readability sake - int size_1 = ((int *)specmallocptr)[0]; - int size_2 = ((int *)specmallocptr)[1]; - int size_3 = ((int *)specmallocptr)[2]; + int cleanModelOfs = ((int *)specmallocptr)[0]; + int damModelOfs = ((int *)specmallocptr)[1]; + int lowModelOfs = ((int *)specmallocptr)[2]; - lastCleanBlock = size_1 + CDSECTOR_SIZE + 11; - lastCleanBlock >>= 11; + lastCleanBlock = cleanModelOfs + CDSECTOR_SIZE + 11; + firstDamBlock = cleanModelOfs + 12; + firstLowBlock = cleanModelOfs + damModelOfs + 12; - firstDamBlock = size_1 + 12; + // to sector index + lastCleanBlock >>= 11; firstDamBlock >>= 11; - - firstLowBlock = size_1 + size_2 + 12; firstLowBlock >>= 11; - int lastDamBlock = size_1 + size_2 + CDSECTOR_SIZE + 11; - lastDamBlock >>= 11; + lastDamBlock = cleanModelOfs + damModelOfs + CDSECTOR_SIZE + 11; + lastLowBlock = cleanModelOfs + damModelOfs + lowModelOfs + CDSECTOR_SIZE + 11; - lengthDamBlock = lastDamBlock - firstDamBlock; - damOffset = size_1 - (firstDamBlock * CDSECTOR_SIZE - 12); - - int lastLowBlock = size_1 + size_2 + size_3 + CDSECTOR_SIZE + 11; + // to sector index + lastDamBlock >>= 11; lastLowBlock >>= 11; + lengthDamBlock = lastDamBlock - firstDamBlock; lengthLowBlock = lastLowBlock - firstLowBlock; - lowOffset = size_1 + size_2 - (firstLowBlock * CDSECTOR_SIZE - 12); - } - model = (MODEL *)(specmallocptr + 12); + lowOffset = cleanModelOfs + damModelOfs - (firstLowBlock * CDSECTOR_SIZE - 12); + damOffset = cleanModelOfs - (firstDamBlock * CDSECTOR_SIZE - 12); + + // mark the memory start for all special models + modelMemory = (int*)specmallocptr; - if (specBlocksToLoad == 7-lastCleanBlock) - { #if USE_PC_FILESYSTEM if (gContentOverride) { - // [A] vertices - LoadCarModelFromFile((char*)model, MissionHeader->residentModels[4], CAR_MODEL_CLEAN); + char* mem; + + if (mem = LoadCarModelFromFile((char*)modelMemory, MissionHeader->residentModels[4], CAR_MODEL_CLEAN)) + { + gCarCleanModelPtr[4] = (MODEL*)modelMemory; + + model = GetCarModel(mem, (char**)&modelMemory, 1); + + whichCP = baseSpecCP; + buildNewCarFromModel(&NewCarModel[4], model, 0); + + specBlocksToLoad = 0; + specialState = SpecSpool_CleanModel; + } + + if (mem = LoadCarModelFromFile((char*)modelMemory, MissionHeader->residentModels[4], CAR_MODEL_DAMAGED)) + { + gCarDamModelPtr[4] = (MODEL*)modelMemory; + + model = GetCarModel(mem, (char**)&modelMemory, 0); + + specBlocksToLoad = 0; + specialState = SpecSpool_DamagedModel; + } + + if (mem = LoadCarModelFromFile((char*)modelMemory, MissionHeader->residentModels[4], CAR_MODEL_LOWDETAIL)) + { + gCarLowModelPtr[4] = (MODEL*)modelMemory; + + model = GetCarModel(mem, (char**)&modelMemory, 1); + + buildNewCarFromModel(&NewLowCarModel[4], model, 0); + + specBlocksToLoad = 0; + specialState = SpecSpool_LowModel; + } } #endif - + } + + // Spooled clean car models are guaranteed to be split in two instances + // this one is polygons only + if (specBlocksToLoad == 7 - lastCleanBlock) + { + specBlocksToLoad = 0; + + model = (MODEL*)(specmallocptr + sizeof(int) * 3); + model->vertices += (int)model; model->poly_block += (int)model; model->normals += (int)model; model->point_normals += (int)model; whichCP = baseSpecCP; - buildNewCarFromModel(&NewCarModel[4], model, 0); - specBlocksToLoad = 0; } if (quickSpool != 1) @@ -1955,14 +1967,6 @@ void LowSpooled(void) if (specBlocksToLoad == 0) { model = (MODEL *)(specmallocptr + lowOffset); - -#if USE_PC_FILESYSTEM - if (gContentOverride) - { - // [A] vertices - LoadCarModelFromFile((char*)model, MissionHeader->residentModels[4], CAR_MODEL_LOWDETAIL); - } -#endif model->vertices += (int)model; model->normals += (int)model; @@ -1983,51 +1987,31 @@ void Tada(void) int spec_tpage; RECT16 tpagerect; - if (specialState == 2) + switch (specialState) { - tpagerect.w = 64; - tpagerect.h = 16; + case SpecSpool_Tpage1: + case SpecSpool_Tpage2: + spec_tpage = specialSlot + (specialState - 1); + tpagerect.w = 64; + tpagerect.h = 16; - spec_tpage = specialSlot + 1; - tpagerect.x = tpagepos[spec_tpage].x; - tpagerect.y = tpagepos[spec_tpage].y + (15 - specBlocksToLoad) * 16; + tpagerect.x = tpagepos[spec_tpage].x; + tpagerect.y = tpagepos[spec_tpage].y + (15 - specBlocksToLoad) * 16; - if (specBlocksToLoad == 15) - update_slotinfo(specTpages[GameLevel][specspooldata[2]-1], specialSlot, &tpagerect); - - LoadImage(&tpagerect, (u_long *)specLoadBuffer); - } - else - { - if (specialState > 2) - { - if (specialState != 4) - return; + if (specBlocksToLoad == 15) + update_slotinfo(specTpages[GameLevel][specSpoolModelIndex-1], specialSlot, &tpagerect); + LoadImage(&tpagerect, (u_long*)specLoadBuffer); + break; + case SpecSpool_Cluts: + SpecClutsSpooled(); + break; + case SpecSpool_Cosmetics: SetupSpecCosmetics(specLoadBuffer); SetupSpecDenting(specLoadBuffer + sizeof(CAR_COSMETICS)); - - if (quickSpool == 1) - return; - - DrawSyncCallback(SpecialStartNextBlock); - return; - } - - if (specialState != 1) - return; - - spec_tpage = specialSlot; - tpagerect.w = 64; - tpagerect.h = 16; - - tpagerect.x = tpagepos[spec_tpage].x; - tpagerect.y = tpagepos[spec_tpage].y + (15 - specBlocksToLoad) * 16; - - if (specBlocksToLoad == 15) - update_slotinfo(specTpages[GameLevel][specspooldata[2]-1], spec_tpage, &tpagerect); - - LoadImage(&tpagerect, (u_long *)specLoadBuffer); + break; + default: + printWarning("Tada: incorrect special state %d", specialState); } if (quickSpool != 1) @@ -2042,79 +2026,78 @@ void SpecialStartNextBlock(void) spooledFuncPtr spoolFunc; loadaddr = specLoadBuffer; - DrawSyncCallback(0); + DrawSyncCallback(NULL); // if previous state blocks are fully loaded, start next state if (specBlocksToLoad == 0) { + specialState++; switch (specialState) { - case 0: - case 1: + case SpecSpool_Tpage1: + case SpecSpool_Tpage2: specBlocksToLoad = 16; break; - case 2: - case 3: + case SpecSpool_Cluts: + case SpecSpool_Cosmetics: specBlocksToLoad = 1; break; - case 4: + case SpecSpool_CleanSpool: specBlocksToLoad = 7; break; - case 5: - case 8: + case SpecSpool_LowSpool: + case SpecSpool_LowModel: specBlocksToLoad = lengthLowBlock; break; - case 6: + case SpecSpool_CleanModel: specBlocksToLoad = lastCleanBlock; break; - case 7: + case SpecSpool_DamagedModel: specBlocksToLoad = lengthDamBlock; break; default: specBlocksToLoad = 0; } - - specialState++; } - fileSector = 0x1400 + (citystart[GameLevel] - SpoolLumpOffset / CDSECTOR_SIZE) + (specspooldata[2]-1) * 42; + fileSector = 0x1400 + (citystart[GameLevel] - SpoolLumpOffset / CDSECTOR_SIZE) + (specSpoolModelIndex-1) * 42; switch (specialState) { - case 1: + case SpecSpool_Tpage1: spoolFunc = Tada; fileSector += (17 - specBlocksToLoad); break; - case 2: + case SpecSpool_Tpage2: spoolFunc = Tada; fileSector += (33 - specBlocksToLoad); break; - case 3: - spoolFunc = SpecClutsSpooled; + case SpecSpool_Cluts: + spoolFunc = Tada; break; - case 4: + case SpecSpool_Cosmetics: fileSector += 33; spoolFunc = Tada; break; - case 5: + case SpecSpool_CleanSpool: spoolFunc = CleanSpooled; fileSector += (41 - specBlocksToLoad); loadaddr = specmallocptr + (7 - specBlocksToLoad) * CDSECTOR_SIZE; break; - case 6: + case SpecSpool_LowSpool: spoolFunc = LowSpooled; fileSector += ((firstLowBlock + lengthLowBlock) - specBlocksToLoad) + 34; loadaddr = specmallocptr + (lengthLowBlock - specBlocksToLoad) * CDSECTOR_SIZE; break; - case 7: + case SpecSpool_CleanModel: spoolFunc = CleanModelSpooled; fileSector += (lastCleanBlock - specBlocksToLoad) + 34; break; - case 8: + case SpecSpool_DamagedModel: spoolFunc = DamagedModelSpooled; fileSector += ((firstDamBlock + lengthDamBlock) - specBlocksToLoad) + 34; break; - case 9: + case SpecSpool_LowModel: spoolFunc = LowModelSpooled; fileSector += ((firstLowBlock + lengthLowBlock) - specBlocksToLoad) + 34; break; @@ -2122,7 +2105,7 @@ void SpecialStartNextBlock(void) if (quickSpool == 1) { specModelValid = 1; - specialState = 0; + specialState = SpecSpool_None; quickSpool = 0; specSpoolComplete = 0; return; @@ -2132,7 +2115,7 @@ void SpecialStartNextBlock(void) return; } - RequestSpool(3, 0, fileSector, 1, loadaddr, spoolFunc); + RequestSpool(SPOOL_MISC, 0, fileSector, 1, loadaddr, spoolFunc); specBlocksToLoad--; } @@ -2156,7 +2139,7 @@ void CheckSpecialSpool(void) } specModelValid = 1; - specialState = 0; + specialState = SpecSpool_None; specBlocksToLoad = 0; specSpoolComplete = 0; startSpecSpool = -1; @@ -2164,6 +2147,7 @@ void CheckSpecialSpool(void) if (allowSpecSpooling && specSpoolComplete != 1 && + specialState == SpecSpool_None && GameType != GAME_PURSUIT && LoadedArea != -1 && SpecialByRegion[GameLevel][LoadedArea] != MissionHeader->residentModels[4]-7) @@ -2187,11 +2171,10 @@ void CheckSpecialSpool(void) gCarCleanModelPtr[4] = NULL; gCarLowModelPtr[4] = NULL; - specspooldata[2] = SpecialByRegion[GameLevel][LoadedArea]; + specSpoolModelIndex = SpecialByRegion[GameLevel][LoadedArea]; MissionHeader->residentModels[4] = SpecialByRegion[GameLevel][LoadedArea] + 7; - if (specialState == 0) - SpecialStartNextBlock(); + SpecialStartNextBlock(); } } @@ -2199,14 +2182,14 @@ void CheckSpecialSpool(void) void QuickSpoolSpecial(void) { quickSpool = 1; - specialState = 0; + specialState = SpecSpool_None; specBlocksToLoad = 0; gCarCleanModelPtr[4] = NULL; gCarDamModelPtr[4] = NULL; gCarLowModelPtr[4] = NULL; - specspooldata[2] = MissionHeader->residentModels[4]-7; + specSpoolModelIndex = MissionHeader->residentModels[4]-7; do { SpoolSYNC(); @@ -2226,11 +2209,11 @@ void PrepareSecretCar(void) gCarCleanModelPtr[4] = NULL; gCarLowModelPtr[4] = NULL; - specspooldata[2] = 5; + specSpoolModelIndex = 5; specModelValid = 0; startSpecSpool = CameraCnt; MissionHeader->residentModels[4] = 12; - specialState = 0; + specialState = SpecSpool_None; specBlocksToLoad = 0; SpecialStartNextBlock(); } @@ -2327,7 +2310,7 @@ void InitSpecSpool(void) #endif specModelValid = 1; - specialState = 0; + specialState = SpecSpool_None; specBlocksToLoad = 0; quickSpool = 0; specSpoolComplete = 0; diff --git a/src_rebuild/Game/C/sysclock.c b/src_rebuild/Game/C/sysclock.c index dd5799e3d..5f299eed7 100644 --- a/src_rebuild/Game/C/sysclock.c +++ b/src_rebuild/Game/C/sysclock.c @@ -8,12 +8,12 @@ int timerflag = 0; int timerhz; int reentryflag; -long tickset; -long tickval; -long ticks; -long libticks = 0; -long g_currentthread = 1; -long timerevent; +int tickset; +int tickval; +int ticks; +int libticks = 0; +int g_currentthread = 1; +int timerevent; void resettick() { @@ -30,7 +30,7 @@ void savegp(long* st) { } -void restoregp(long gp) +void restoregp(int gp) { } @@ -64,9 +64,9 @@ long tmrint(void) } /* -void timedwait(long ms) +void timedwait(int ms) { - long oldTick; + int oldTick; oldTick = gettick(); @@ -109,9 +109,9 @@ void inittimer(int hz) { if (hz == 0) hz = 100; - +#ifdef PSX EnterCriticalSection(); - +#endif if (timerflag == 0) { memset((u_char*)&tmrsub, 0, sizeof(tmrsub)); @@ -138,7 +138,9 @@ void inittimer(int hz) SetRCnt(RCntCNT2, (4233600 / hz), EvSpTRAP); StartRCnt(RCntCNT2); +#ifdef PSX ExitCriticalSection(); +#endif resettick(); //addexit(restoretimer); diff --git a/src_rebuild/Game/C/system.c b/src_rebuild/Game/C/system.c index ac185f3d6..505d5c563 100644 --- a/src_rebuild/Game/C/system.c +++ b/src_rebuild/Game/C/system.c @@ -58,7 +58,7 @@ volatile char* _replay_buffer = NULL; // 0x1FABBC #if defined(USE_CRT_MALLOC) -char* mallocptr = NULL; +volatile char* mallocptr = NULL; volatile char* malloctab = NULL; void* g_dynamicAllocs[1024] = { 0 }; @@ -627,7 +627,6 @@ void DisableDisplay(void) SetDispMask(0); } -int DoNotSwap = 0; DB* MPlast[2]; DB* MPcurrent[2]; @@ -643,13 +642,7 @@ void SwapDrawBuffers(void) { DrawSync(0); - if (DoNotSwap == 0) - { - PutDispEnv(¤t->disp); - } - - DoNotSwap = 0; - + PutDispEnv(¤t->disp); PutDrawEnv(¤t->draw); DrawOTag((u_long*)(current->ot + OTSIZE-1)); @@ -664,7 +657,8 @@ void SwapDrawBuffers(void) last = &MPBuff[0][0]; } - ClearCurrentDrawBuffers(); + ClearOTagR((u_long*)current->ot, OTSIZE); + current->primptr = current->primtab; } // [D] [T] @@ -680,17 +674,17 @@ void SwapDrawBuffers2(int player) } PutDrawEnv(¤t->draw); - DrawOTag((u_long*)(current->ot + OTSIZE - 1)); + DrawOTag((u_long*)(current->ot + OTSIZE-1)); if (player == 1) { toggle = FrameCnt & 1; // [A] i guess it should work as intended - MPcurrent[0] = &MPBuff[0][-toggle + 1]; + MPcurrent[0] = &MPBuff[0][1-toggle]; MPlast[0] = &MPBuff[0][toggle]; - MPcurrent[1] = &MPBuff[1][-toggle + 1]; + MPcurrent[1] = &MPBuff[1][1-toggle]; MPlast[1] = &MPBuff[1][toggle]; } @@ -734,6 +728,8 @@ void SetupDrawBuffers(void) MPBuff[0][1].disp.screen.h = SCREEN_H; MPBuff[0][0].disp.screen.x = draw_mode.framex; MPBuff[0][1].disp.screen.x = draw_mode.framex; + MPBuff[0][0].disp.screen.y = draw_mode.framey; + MPBuff[0][1].disp.screen.y = draw_mode.framey; if (NoPlayerControl == 0) SetupDrawBufferData(NumPlayers); @@ -795,26 +791,26 @@ void SetupDrawBufferData(int num_players) { for (j = 0; j < num_players; j++) { - u_long* otpt; + u_int* otpt; u_char* primpt; if (toggle) { - otpt = (u_long*)_OT2; + otpt = (u_int*)_OT2; primpt = (u_char*)_primTab2; // _primTab1 + PRIMTAB_SIZE } else { - otpt = (u_long*)_OT1; + otpt = (u_int*)_OT1; primpt = (u_char*)_primTab1; } toggle ^= 1; InitaliseDrawEnv(MPBuff[j], x[j], y[j], 320, height); - MPBuff[i][j].primtab = (char*)primpt; - MPBuff[i][j].primptr = (char*)primpt; - MPBuff[i][j].ot = (OTTYPE*)otpt; + MPBuff[j][i].primtab = (char*)primpt; + MPBuff[j][i].primptr = (char*)primpt; + MPBuff[j][i].ot = (OTTYPE*)otpt; } } @@ -830,17 +826,8 @@ void SetupDrawBufferData(int num_players) // [D] [T] void InitaliseDrawEnv(DB* pBuff, int x, int y, int w, int h) { -#ifdef PSX -#define DB1 pBuff[0] -#define DB2 pBuff[1] -#else -// on PsyX we have to prevent flicker -#define DB1 pBuff[1] -#define DB2 pBuff[0] -#endif - - SetDefDrawEnv(&DB1.draw, x, y, w, h); - SetDefDrawEnv(&DB2.draw, x, y + 256, w, h); + SetDefDrawEnv(&pBuff[0].draw, x, y, w, h); + SetDefDrawEnv(&pBuff[1].draw, x, y + 256, w, h); pBuff[0].id = 0; pBuff[0].draw.dfe = 1; @@ -848,7 +835,8 @@ void InitaliseDrawEnv(DB* pBuff, int x, int y, int w, int h) pBuff[1].id = 1; pBuff[1].draw.dfe = 1; -#ifdef USE_PGXP +#if USE_PGXP + // extend clip rectangles for widscreen if(NumPlayers == 2) { pBuff[0].draw.clip.x -= 256; diff --git a/src_rebuild/Game/C/system.h b/src_rebuild/Game/C/system.h index 5ab055e34..477c4b77d 100644 --- a/src_rebuild/Game/C/system.h +++ b/src_rebuild/Game/C/system.h @@ -59,7 +59,7 @@ extern void sys_freeall(); #define D_TEMPALLOC(size) sys_tempalloc(size) #ifdef _DEBUG -#define D_MALLOC(size) sys_malloc(size, __FUNCTION__, __LINE__) +#define D_MALLOC(size) sys_malloc(size, FUNCNAME, __LINE__) #else #define D_MALLOC(size) sys_malloc(size, NULL, 0) @@ -85,13 +85,13 @@ extern void sys_freeall(); #define D_MALLOC_END() \ D_TEMPFREE();\ if(mallocptr > _oldmalloc)\ - DMalloc_DebugPrint("malloc(%d) in %s, line %d. Malloc usage: %d\n", mallocptr-_oldmalloc, __FUNCTION__, __LINE__, (mallocptr-malloctab));\ + DMalloc_DebugPrint("malloc(%d) in %s, line %d. Malloc usage: %d\n", mallocptr-_oldmalloc, FUNCNAME, __LINE__, (mallocptr-malloctab));\ } // D_MALLOC_BEGIN block #else #define D_MALLOC_END() \ D_TEMPFREE();\ if(mallocptr > _oldmalloc)\ - DMalloc_DebugPrint("malloc(%d) in " __FUNCTION__ ", line %d. Malloc usage: %d\n", mallocptr-_oldmalloc, __LINE__, (mallocptr-malloctab));\ + DMalloc_DebugPrint("malloc(%d) in " FUNCNAME ", line %d. Malloc usage: %d\n", mallocptr-_oldmalloc, __LINE__, (mallocptr-malloctab));\ } // D_MALLOC_BEGIN block #endif @@ -139,7 +139,7 @@ extern DRAW_MODE draw_mode_ntsc; #define OTSIZE 0x2000 #endif -#ifdef USE_EXTENDED_PRIM_POINTERS +#if USE_EXTENDED_PRIM_POINTERS # define PRIMTAB_SIZE 0x50000 #else # define PRIMTAB_SIZE 0x1e000 diff --git a/src_rebuild/Game/C/targets.c b/src_rebuild/Game/C/targets.c index 952c94683..c8f0722e6 100644 --- a/src_rebuild/Game/C/targets.c +++ b/src_rebuild/Game/C/targets.c @@ -281,7 +281,7 @@ void DrawStopZone(VECTOR *pPosition) SVECTOR temp; long p; long flag; - long sz; + int sz; int flash; int height; @@ -326,7 +326,7 @@ void DrawStopZone(VECTOR *pPosition) RotTransPers(&temp, pOut, &p, &flag); - if (pOut == (long*)&pPoly->x0) + if (pOut == (long*)&pPoly->x0) pOut = (long*)&pPoly->x1; else if (pOut == (long*)&pPoly->x1) pOut = (long*)&pPoly->x2; @@ -347,7 +347,7 @@ void DrawStopZone(VECTOR *pPosition) *(ushort*)&pPoly->u2 = *(ushort*)&light_texture.coords.u2; *(ushort*)&pPoly->u3 = *(ushort*)&light_texture.coords.u3; - if (gTimeOfDay == 3) + if (gTimeOfDay == TIME_NIGHT) pPoly->tpage = light_texture.tpageid | 0x20; else pPoly->tpage = light_texture.tpageid | 0x40; diff --git a/src_rebuild/Game/C/texture.c b/src_rebuild/Game/C/texture.c index 36658873f..bdc4e8699 100644 --- a/src_rebuild/Game/C/texture.c +++ b/src_rebuild/Game/C/texture.c @@ -193,7 +193,7 @@ void LoadTPageFromTIMs(int tpage2send) tmptpage.w = timData->width; tmptpage.h = timData->height; - LoadImage(&tmptpage, (u_long *)((char*)timData + sizeof(TIMIMAGEHDR))); + LoadImage(&tmptpage, (u_long*)((char*)timData + sizeof(TIMIMAGEHDR))); // get through all it's CLUTs // and replace @@ -225,7 +225,7 @@ void LoadTPageFromTIMs(int tpage2send) tmpclut.w = 16; tmpclut.h = 1; - LoadImage(&tmpclut, (u_long *)((char*)timClut + sizeof(TIMIMAGEHDR) + j * 32)); + LoadImage(&tmpclut, (u_long*)((char*)timClut + sizeof(TIMIMAGEHDR) + j * 32)); } } } @@ -245,7 +245,7 @@ int LoadTPageAndCluts(RECT16 *tpage, RECT16 *cluts, int tpage2send, char *tpagea for (i = 0; i < npalettes; i++) { - LoadImage(cluts, (u_long *)tpageaddress); + LoadImage(cluts, (u_long*)tpageaddress); tpageaddress += 32; texture_cluts[tpage2send][i] = GetClut(cluts->x, cluts->y); @@ -259,7 +259,7 @@ int LoadTPageAndCluts(RECT16 *tpage, RECT16 *cluts, int tpage2send, char *tpagea temptpage.h = 256; decomp_asm((char*)_other_buffer, tpageaddress); - LoadImage(&temptpage, (u_long *)_other_buffer); + LoadImage(&temptpage, (u_long*)_other_buffer); texture_pages[tpage2send] = GetTPage(0, 0, tpage->x, tpage->y); IncrementTPageNum(tpage); diff --git a/src_rebuild/Game/C/tile.c b/src_rebuild/Game/C/tile.c index a655df4d5..3533ae8c4 100644 --- a/src_rebuild/Game/C/tile.c +++ b/src_rebuild/Game/C/tile.c @@ -8,6 +8,117 @@ #include "ASM/rndrasm.h" +#ifdef PSX +#pragma GCC optimization ("O3") +#endif + +#ifdef DYNAMIC_LIGHTING +void Tile1x1Lit(MODEL* model) +{ + int opz, Z; + int ofse; + PL_POLYFT4* polys; + int i; + u_char ptype; + POLY_GT4* prims; + SVECTOR* srcVerts; + + srcVerts = (SVECTOR*)model->vertices; + polys = (PL_POLYFT4*)model->poly_block; + + // grass should be under pavements and other things + if ((model->shape_flags & SHAPE_FLAG_WATER) || (model->flags2 & MODEL_FLAG_GRASS)) + ofse = 229; + else + ofse = 133; + +#if USE_PGXP + PGXP_SetZOffsetScale(0.0f, ofse > 200 ? 1.005f : 0.995f); +#endif + + i = model->num_polys; + while (i-- > 0) + { + // iterate through polygons + // with skipping + ptype = polys->id & 0x1f; + + // perform transform + gte_ldv3(&srcVerts[polys->v0], &srcVerts[polys->v1], &srcVerts[polys->v3]); + gte_rtpt(); + + // get culling value + gte_nclip(); + gte_stopz(&opz); + + if (opz > 0) + { + prims = (POLY_GT4*)plotContext.primptr; + + *(uint*)&prims->r0 = plotContext.colour; + *(uint*)&prims->r1 = plotContext.colour; + *(uint*)&prims->r2 = plotContext.colour; + *(uint*)&prims->r3 = plotContext.colour; + setPolyGT4(prims); + + // retrieve first three verts + gte_stsxy3(&prims->x0, &prims->x1, &prims->x2); + + // translate 4th vert and get OT Z value + gte_ldv0(&srcVerts[polys->v2]); + gte_rtps(); + gte_avsz4(); + + gte_stotz(&Z); + + gte_stsxy(&prims->x3); + + prims->tpage = (*plotContext.ptexture_pages)[polys->texture_set]; + prims->clut = (*plotContext.ptexture_cluts)[polys->texture_set][polys->texture_id]; + + *(ushort*)&prims->u0 = *(ushort*)&polys->uv0; + *(ushort*)&prims->u1 = *(ushort*)&polys->uv1; + *(ushort*)&prims->u2 = *(ushort*)&polys->uv3; + *(ushort*)&prims->u3 = *(ushort*)&polys->uv2; + + SVECTOR tmpPos; + gte_ldv0(&srcVerts[polys->v0]); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prims->r0); + + gte_ldv0(&srcVerts[polys->v1]); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prims->r1); + + gte_ldv0(&srcVerts[polys->v3]); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prims->r2); + + gte_ldv0(&srcVerts[polys->v2]); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prims->r3); + + addPrim(plotContext.ot + (Z >> 1) + ofse, prims); + + plotContext.primptr += sizeof(POLY_GT4); + } + + polys = (PL_POLYFT4*)((char*)polys + plotContext.polySizes[ptype]); + } + +#if USE_PGXP + PGXP_SetZOffsetScale(0.0f, 1.0f); +#endif + + // done + plotContext.current->primptr = plotContext.primptr; +} +#endif + // [D] [T] [A] void Tile1x1(MODEL *model) { @@ -28,7 +139,7 @@ void Tile1x1(MODEL *model) else ofse = 133; -#ifdef USE_PGXP +#if USE_PGXP PGXP_SetZOffsetScale(0.0f, ofse > 200 ? 1.005f : 0.995f); #endif @@ -51,9 +162,9 @@ void Tile1x1(MODEL *model) { prims = (POLY_FT4*)plotContext.primptr; + *(uint*)&prims->r0 = plotContext.colour; setPolyFT4(prims); - *(ulong*)&prims->r0 = plotContext.colour; - + // retrieve first three verts gte_stsxy3(&prims->x0, &prims->x1, &prims->x2); @@ -82,7 +193,7 @@ void Tile1x1(MODEL *model) polys = (PL_POLYFT4*)((char*)polys + plotContext.polySizes[ptype]); } -#ifdef USE_PGXP +#if USE_PGXP PGXP_SetZOffsetScale(0.0f, 1.0f); #endif @@ -90,6 +201,19 @@ void Tile1x1(MODEL *model) plotContext.current->primptr = plotContext.primptr; } +// performs division by 3 or by 5 depending on t +inline int fst_div_lut_3_5(int x, int t) +{ + static int mul[] = { 171, 205 }; + return x * mul[t] >> (9 + t); +} + +inline int fst_div_3(int x) +{ + return x * 171 >> 9; +} + + // [D] [T] void DrawTILES(PACKED_CELL_OBJECT** tiles, int tile_amount) { @@ -101,13 +225,20 @@ void DrawTILES(PACKED_CELL_OBJECT** tiles, int tile_amount) if (gTimeOfDay > -1) { - if (gTimeOfDay < 3) + int combo = combointensity; + if (gTimeOfDay < TIME_NIGHT) { - plotContext.colour = combointensity & 0xffffffU | 0x2C000000; + plotContext.colour = combo & 0xffffffU | 0x2C000000; } - else if (gTimeOfDay == 3) + else if (gTimeOfDay == TIME_NIGHT) { - plotContext.colour = ((combointensity >> 16 & 255) / 3) << 16 | ((combointensity >> 8 & 255) / 3) << 8 | (combointensity & 255) / 3 | 0x2C000000U; +#ifdef DYNAMIC_LIGHTING + int t; + t = GameLevel == 2 && gEnableDlights == 1; + plotContext.colour = fst_div_lut_3_5(combo >> 16 & 255, t) << 16 | fst_div_lut_3_5(combo >> 8 & 255, t) << 8 | fst_div_lut_3_5(combo & 255, t) | 0x2C000000U; +#else + plotContext.colour = fst_div_3(combo >> 16 & 255) << 16 | fst_div_3(combo >> 8 & 255) << 8 | fst_div_3(combo & 255) | 0x2C000000U; +#endif } } @@ -116,7 +247,7 @@ void DrawTILES(PACKED_CELL_OBJECT** tiles, int tile_amount) if (gWeather - 1U < 2) { u_int col; - col = plotContext.colour >> 2 & 0x3f; + col = plotContext.colour >> 2 & 63; plotContext.colour = col * 0x30000 | col * 0x300 | col * 3 | 0x2C000000; } @@ -125,7 +256,6 @@ void DrawTILES(PACKED_CELL_OBJECT** tiles, int tile_amount) plotContext.primptr = current->primptr; plotContext.ptexture_pages = (ushort(*)[128])texture_pages; plotContext.ptexture_cluts = (ushort(*)[128][32])texture_cluts; - plotContext.lastTexInfo = 0x18273472; plotContext.flags = 0; plotContext.polySizes = PolySizes; @@ -135,20 +265,20 @@ void DrawTILES(PACKED_CELL_OBJECT** tiles, int tile_amount) { ppco = *tilePointers++; - plotContext.f4colourTable[6] = ppco->pos.vx; - plotContext.f4colourTable[7] = (ppco->pos.vy << 0x10) >> 0x11; - plotContext.f4colourTable[8] = ppco->pos.vz; + plotContext.scribble[0] = ppco->pos.vx; + plotContext.scribble[1] = (ppco->pos.vy << 0x10) >> 0x11; + plotContext.scribble[2] = ppco->pos.vz; yang = ppco->value & 0x3f; model_number = (ppco->value >> 6) | (ppco->pos.vy & 1) << 10; if (previous_matrix == yang) { - Z = Apply_InvCameraMatrixSetTrans((VECTOR_NOPAD *)(plotContext.f4colourTable + 6)); + Z = Apply_InvCameraMatrixSetTrans((VECTOR_NOPAD *)plotContext.scribble); } else { - Z = Apply_InvCameraMatrixAndSetMatrix((VECTOR_NOPAD *)(plotContext.f4colourTable + 6), &CompoundMatrix[previous_matrix = yang]); + Z = Apply_InvCameraMatrixAndSetMatrix((VECTOR_NOPAD *)plotContext.scribble, &CompoundMatrix[previous_matrix = yang]); } if (Z <= DRAW_LOD_DIST_HIGH) @@ -160,14 +290,18 @@ void DrawTILES(PACKED_CELL_OBJECT** tiles, int tile_amount) if (Z < 2000) TileNxN(pModel, 4, 75); - else + else TileNxN(pModel, 2, 35); } else { pModel = Z > DRAW_LOD_DIST_LOW ? pLodModels[model_number] : modelpointers[model_number]; +#ifdef DYNAMIC_LIGHTING + (gEnableDlights ? Tile1x1Lit : Tile1x1)(pModel); +#else Tile1x1(pModel); +#endif // DYNAMIC_LIGHTING } } current->primptr = plotContext.primptr; @@ -206,31 +340,31 @@ void makeMesh(MVERTEX(*VSP)[5][5], int m, int n) v4 = (*VSP)[0][2]; VecSubtract(&e1, &v2, &v1); // plane[1] - plane[0]; - e1.uv.s.u0 = (v2.uv.s.u0 - v1.uv.s.u0) / 2; - e1.uv.s.v0 = (v2.uv.s.v0 - v1.uv.s.v0) / 2; + e1.uv.s.u0 = (v2.uv.s.u0 - v1.uv.s.u0) >> 1; + e1.uv.s.v0 = (v2.uv.s.v0 - v1.uv.s.v0) >> 1; VecSubtract(&e2, &v3, &v4); // plane[2] - plane[3]; - e2.uv.s.u0 = (v3.uv.s.u0 - v4.uv.s.u0) / 2; - e2.uv.s.v0 = (v3.uv.s.v0 - v4.uv.s.v0) / 2; + e2.uv.s.u0 = (v3.uv.s.u0 - v4.uv.s.u0) >> 1; + e2.uv.s.v0 = (v3.uv.s.v0 - v4.uv.s.v0) >> 1; VecSubtract(&e3, &v4, &v1); // plane[3] - plane[0]; - e3.uv.s.u0 = (v4.uv.s.u0 - v1.uv.s.u0) / 2; - e3.uv.s.v0 = (v4.uv.s.v0 - v1.uv.s.v0) / 2; + e3.uv.s.u0 = (v4.uv.s.u0 - v1.uv.s.u0) >> 1; + e3.uv.s.v0 = (v4.uv.s.v0 - v1.uv.s.v0) >> 1; VecSubtract(&e4, &v3, &v2); // plane[2] - plane[1]; - e4.uv.s.u0 = (v3.uv.s.u0 - v2.uv.s.u0) / 2; - e4.uv.s.v0 = (v3.uv.s.v0 - v2.uv.s.v0) / 2; + e4.uv.s.u0 = (v3.uv.s.u0 - v2.uv.s.u0) >> 1; + e4.uv.s.v0 = (v3.uv.s.v0 - v2.uv.s.v0) >> 1; //----------- // half them all - SetVec(&e1, e1.vx / 2, e1.vy / 2, e1.vz / 2); + SetVec(&e1, e1.vx >> 1, e1.vy >> 1, e1.vz >> 1); - SetVec(&e2, e2.vx / 2, e2.vy / 2, e2.vz / 2); + SetVec(&e2, e2.vx >> 1, e2.vy >> 1, e2.vz >> 1); - SetVec(&e3, e3.vx / 2, e3.vy / 2, e3.vz / 2); + SetVec(&e3, e3.vx >> 1, e3.vy >> 1, e3.vz >> 1); - SetVec(&e4, e4.vx / 2, e4.vy / 2, e4.vz / 2); + SetVec(&e4, e4.vx >> 1, e4.vy >> 1, e4.vz >> 1); //----------- @@ -253,10 +387,10 @@ void makeMesh(MVERTEX(*VSP)[5][5], int m, int n) //----------- VecSubtract(&e5, &p2, &p1); // p2 - p1; - e5.uv.s.u0 = (p2.uv.s.u0 - p1.uv.s.u0) / 2; - e5.uv.s.v0 = (p2.uv.s.v0 - p1.uv.s.v0) / 2; + e5.uv.s.u0 = (p2.uv.s.u0 - p1.uv.s.u0) >> 1; + e5.uv.s.v0 = (p2.uv.s.v0 - p1.uv.s.v0) >> 1; - SetVec(&e5, e5.vx / 2, e5.vy / 2, e5.vz / 2); + SetVec(&e5, e5.vx >> 1, e5.vy >> 1, e5.vz >> 1); VecAdd(&p5, &e5, &p1); // e5 * 0.5f + p1; @@ -309,7 +443,7 @@ void drawMesh(MVERTEX(*VSP)[5][5], int m, int n, _pct *pc) for (int index = 0; index < numPolys; index++) { setPolyFT4(prim); - *(ulong*)&prim->r0 = pc->colour; // FIXME: semiTransparency support + *(uint*)&prim->r0 = pc->colour; // FIXME: semiTransparency support // test gte_ldv3(&(*VSP)[index][0], &(*VSP)[index][1], &(*VSP)[index][2]); @@ -336,7 +470,6 @@ void drawMesh(MVERTEX(*VSP)[5][5], int m, int n, _pct *pc) gte_ldv0(&(*VSP)[index][3]); gte_rtps(); - gte_stsxy(&prim->x3); *(ushort*)&prim->u0 = (*VSP)[index][0].uv.val; @@ -344,8 +477,8 @@ void drawMesh(MVERTEX(*VSP)[5][5], int m, int n, _pct *pc) *(ushort*)&prim->u2 = (*VSP)[index][2].uv.val; *(ushort*)&prim->u3 = (*VSP)[index][3].uv.val; - prim->clut = pc->clut >> 0x10; - prim->tpage = pc->tpage >> 0x10; + prim->clut = pc->clut; + prim->tpage = pc->tpage; addPrim(pc->ot + (z >> 1), prim); @@ -356,6 +489,102 @@ void drawMesh(MVERTEX(*VSP)[5][5], int m, int n, _pct *pc) pc->primptr = (char*)prim; } +#ifdef DYNAMIC_LIGHTING +void drawMeshLit(MVERTEX(*VSP)[5][5], int m, int n, _pct* pc) +{ + POLY_GT4* prim; + int z, opz; + + prim = (POLY_GT4*)pc->primptr; + + int numPolys = 4; + + if (n < 2) + numPolys = 1; + +#if 0 + // no need to subdivide! + if (g_pgxpZBuffer) + numPolys = 1; +#endif + + for (int index = 0; index < numPolys; index++) + { + setPolyGT4(prim); + + // test + gte_ldv3(&(*VSP)[index][0], &(*VSP)[index][1], &(*VSP)[index][2]); + gte_rtpt(); + gte_nclip(); + gte_stopz(&opz); + + gte_avsz3(); + + gte_stotz(&z); + + if (pc->flags & (PLOT_NO_CULL | PLOT_INV_CULL)) + { + if (pc->flags & PLOT_NO_CULL) + opz = 1; // no culling + else // PLOT_FRONT_CULL + opz = -opz; // front face + } + + if (opz > 0 && z > 5) + { + gte_stsxy3(&prim->x0, &prim->x1, &prim->x2); + + gte_ldv0(&(*VSP)[index][3]); + gte_rtps(); + + gte_stsxy(&prim->x3); + + *(uint*)&prim->r0 = plotContext.colour; + *(uint*)&prim->r1 = plotContext.colour; + *(uint*)&prim->r2 = plotContext.colour; + *(uint*)&prim->r3 = plotContext.colour; + + SVECTOR tmpPos; + gte_ldv0(&(*VSP)[index][0]); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prim->r0); + + gte_ldv0(&(*VSP)[index][1]); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prim->r1); + + gte_ldv0(&(*VSP)[index][2]); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prim->r2); + + gte_ldv0(&(*VSP)[index][3]); + gte_rtps(); + gte_stsv(&tmpPos); + GetDLightLevel(&tmpPos, (u_int*)&prim->r3); + + setPolyGT4(prim); + + * (ushort*)&prim->u0 = (*VSP)[index][0].uv.val; + *(ushort*)&prim->u1 = (*VSP)[index][1].uv.val; + *(ushort*)&prim->u2 = (*VSP)[index][2].uv.val; + *(ushort*)&prim->u3 = (*VSP)[index][3].uv.val; + + prim->clut = pc->clut; + prim->tpage = pc->tpage; + + addPrim(pc->ot + (z >> 1), prim); + + prim++; + } + } + + pc->primptr = (char*)prim; +} +#endif // DYNAMIC_LIGHTING + // [A] custom implemented function void SubdivNxM(char *polys, int n, int m, int ofse) { @@ -365,8 +594,8 @@ void SubdivNxM(char *polys, int n, int m, int ofse) POLYFT4* pft4 = (POLYFT4*)polys; - plotContext.clut = (u_int)(*plotContext.ptexture_cluts)[pft4->texture_set][pft4->texture_id] << 0x10; - plotContext.tpage = (u_int)(*plotContext.ptexture_pages)[pft4->texture_set] << 0x10; + plotContext.clut = (u_int)(*plotContext.ptexture_cluts)[pft4->texture_set][pft4->texture_id]; + plotContext.tpage = (u_int)(*plotContext.ptexture_pages)[pft4->texture_set]; copyVector(&subdivVerts[0][0], &verts[pft4->v0]); subdivVerts[0][0].uv.val = *(ushort*)&pft4->uv0; @@ -383,7 +612,11 @@ void SubdivNxM(char *polys, int n, int m, int ofse) plotContext.ot += ofse; makeMesh((MVERTEX(*)[5][5])subdivVerts, m, n); +#ifdef DYNAMIC_LIGHTING + (gEnableDlights ? drawMeshLit : drawMesh)((MVERTEX(*)[5][5])subdivVerts, m, n, &plotContext); +#else drawMesh((MVERTEX(*)[5][5])subdivVerts, m, n, &plotContext); +#endif plotContext.ot -= ofse; } @@ -419,7 +652,7 @@ void TileNxN(MODEL *model, int levels, int Dofse) ttype = 0; while (i--) { -#ifdef USE_PGXP +#if USE_PGXP switch (ttype) { case 0: @@ -443,7 +676,7 @@ void TileNxN(MODEL *model, int levels, int Dofse) polys += plotContext.polySizes[*polys]; } -#ifdef USE_PGXP +#if USE_PGXP PGXP_SetZOffsetScale(0.0f, 1.0f); #endif } diff --git a/src_rebuild/Game/C/wheelforces.c b/src_rebuild/Game/C/wheelforces.c index 1be49ff73..f6abdb75e 100644 --- a/src_rebuild/Game/C/wheelforces.c +++ b/src_rebuild/Game/C/wheelforces.c @@ -12,6 +12,7 @@ #include "sound.h" #include "glaunch.h" #include "system.h" +#include "cutscene.h" #define GRAVITY_FORCE (-7456) // D1 has -10922 @@ -199,21 +200,18 @@ void AddWheelForcesDriver1(CAR_DATA* cp, CAR_LOCALS* cl) int chan; WHEEL* wheel; int friction_coef; - int oldSpeed; - int wheelspd; - LONGVECTOR4 wheelPos; - LONGVECTOR4 surfacePoint; - LONGVECTOR4 surfaceNormal; + int oldSpeed, wheelspd; + LONGVECTOR4 wheelPos, surfacePoint, surfaceNormal; VECTOR force; LONGVECTOR4 pointVel; - int frontFS; - int rearFS; + int frontFS, rearFS; sdPlane* SurfacePtr; int i; int cdx, cdz; int sdx, sdz; CAR_COSMETICS* car_cos; int player_id; + int oldCutRoughness; oldSpeed = cp->hd.speed * 3 >> 1; @@ -232,6 +230,7 @@ void AddWheelForcesDriver1(CAR_DATA* cp, CAR_LOCALS* cl) player_id = GetPlayerId(cp); car_cos = &car_cosmetics[cp->ap.model]; + oldCutRoughness = gInGameCutsceneActive && gCurrentMissionNumber == 23 && gInGameCutsceneID == 0; // [A] hack moved here GetFrictionScalesDriver1(cp, cl, &frontFS, &rearFS); cp->hd.front_vel = 0; @@ -248,9 +247,23 @@ void AddWheelForcesDriver1(CAR_DATA* cp, CAR_LOCALS* cl) gte_rtv0tr(); gte_stlvnl(wheelPos); - newCompression = FindSurfaceD2((VECTOR*)&wheelPos, (VECTOR*)&surfaceNormal, (VECTOR*)&surfacePoint, &SurfacePtr); + FindSurfaceD2((VECTOR*)&wheelPos, (VECTOR*)&surfaceNormal, (VECTOR*)&surfacePoint, &SurfacePtr); - friction_coef = (newCompression * (32400 - wetness) >> 15) + 500; + if (SurfacePtr && SurfacePtr->surface == SURF_GRASS) + { + int roughness; + roughness = RSIN((surfacePoint[0] + surfacePoint[2]) * 2) >> 8; + + surfacePoint[1] += oldCutRoughness ? (roughness >> 1) : (roughness / 3); + + forcefac = 2048; + } + else + { + forcefac = 4096; + } + + friction_coef = (forcefac * (32400 - wetness) >> 15) + 500; if (SurfacePtr != NULL) wheel->onGrass = SurfacePtr->surface == SURF_GRASS; @@ -603,6 +616,11 @@ void StepOneCar(CAR_DATA* cp) FindSurfaceD2((VECTOR*)pointPos, (VECTOR*)surfaceNormal, (VECTOR*)&surfacePoint, &SurfacePtr); + if (SurfacePtr && SurfacePtr->surface == SURF_GRASS) + { + surfacePoint[1] += (RSIN((surfacePoint[0] + surfacePoint[2]) * 2) >> 8) / 3; + } + if ((surfacePoint[1] - pointPos[1]) - 1U < 799) { int newLift; diff --git a/src_rebuild/Game/C/xaplay.c b/src_rebuild/Game/C/xaplay.c index 9edf613f1..c8e972172 100644 --- a/src_rebuild/Game/C/xaplay.c +++ b/src_rebuild/Game/C/xaplay.c @@ -50,7 +50,7 @@ struct XA_TRACK XA_TRACK XAMissionMessages[4]; -static unsigned long finished_count = 0; +static unsigned int finished_count = 0; static int gPlaying = 0; unsigned short gChannel = 0; static int xa_prepared = 0; @@ -123,7 +123,7 @@ int gNumXASubtitles = 0; int gXASubtitleTime = 0; int gXASubtitlePauseTime = 0; -void PrintXASubtitles() +void PrintXASubtitles(int yPos) { if (gSubtitles == 0 || pauseflag) return; @@ -144,7 +144,7 @@ void PrintXASubtitles() if(curTime >= subStartFrame && curTime <= subEndFrame) { SetTextColour(120, 120, 120); - PrintStringCentred(sub->text, 200); + PrintStringCentred(sub->text, yPos); } } } diff --git a/src_rebuild/Game/C/xaplay.h b/src_rebuild/Game/C/xaplay.h index effc1cb1a..fee156d96 100644 --- a/src_rebuild/Game/C/xaplay.h +++ b/src_rebuild/Game/C/xaplay.h @@ -1,7 +1,7 @@ #ifndef XAPLAY_H #define XAPLAY_H -extern void PrintXASubtitles(); +extern void PrintXASubtitles(int yPos); extern void GetMissionXAData(int number); // 0x00082EC0 extern void GetXAData(int number); // 0x00082D60 diff --git a/src_rebuild/Game/C/xmplay.c b/src_rebuild/Game/C/xmplay.c index 8b7399c65..c0d95611a 100644 --- a/src_rebuild/Game/C/xmplay.c +++ b/src_rebuild/Game/C/xmplay.c @@ -20,7 +20,7 @@ XMPLAY.C SpuVoiceAttr xm_g_s_attr; /* Structure for individual voice attributes*/ SpuVoiceAttr uxm_g_s_attr; /* Structure for individual voice attributes*/ SpuReverbAttr xm_r_attr; /* Structure for reverb */ -unsigned long xm_l_vag_spu_addr[8][128]; /* Address in memory for first sound file */ +unsigned int xm_l_vag_spu_addr[8][128]; /* Address in memory for first sound file */ /**** XM SPECIFIC ****/ @@ -232,7 +232,7 @@ short Interpolate(short p, short p1, short p2, short v1, short v2) dp = p2 - p1; di = p - p1; - return v1 + ((long)(di*dv) / dp); + return v1 + ((int)(di*dv) / dp); } @@ -423,7 +423,7 @@ int InitXMData(u_char *mpp, int XM_ID, int S3MPan) int a; int c; - u_long b; + u_int b; u_short b2; @@ -456,9 +456,9 @@ int InitXMData(u_char *mpp, int XM_ID, int S3MPan) for (t = 0; t < c; t++) { - mhu->JAP_PAT_ADDR[t] = (u_long*)(mpp + a); /* Store Pattern Addr's */ + mhu->JAP_PAT_ADDR[t] = (u_int*)(mpp + a); /* Store Pattern Addr's */ b = GetLong(mpp + a); - mhu->JAP_PAT_ADDR2[t] = (u_long*)(mpp + a + b); /* Store Pattern Addr's */ + mhu->JAP_PAT_ADDR2[t] = (u_int*)(mpp + a + b); /* Store Pattern Addr's */ b2 = getWord(mpp + a + 7); b += b2; a += b; @@ -471,16 +471,16 @@ int InitXMData(u_char *mpp, int XM_ID, int S3MPan) b2 = getWord(mpp + a + 27); if (b2 != 0) { - mhu->JAP_SampAddr[t] = (u_long*)(mpp + 29 + a); - mhu->JAP_SampHdrAddr[t] = (u_long*)(mpp + b + a); + mhu->JAP_SampAddr[t] = (u_int*)(mpp + 29 + a); + mhu->JAP_SampHdrAddr[t] = (u_int*)(mpp + b + a); b += (40 * b2); } else { - mhu->JAP_SampAddr[t] = (u_long*)0xcdcdcdcd; //(u_long*)(mpp+29+a); - mhu->JAP_SampHdrAddr[t] = (u_long*)0x01234567; //(u_long*)(mpp+b+a); + mhu->JAP_SampAddr[t] = (u_int*)0xcdcdcdcd; //(u_int *)(mpp+29+a); + mhu->JAP_SampHdrAddr[t] = (u_int*)0x01234567; //(u_int *)(mpp+b+a); } - mhu->JAP_InstrumentOffset[t] = (u_long*)(mpp + a); /* Store Instrument Addr's*/ + mhu->JAP_InstrumentOffset[t] = (u_int*)(mpp + a); /* Store Instrument Addr's*/ a += b; } return(mhu->XMPSXChannels); @@ -489,16 +489,16 @@ int InitXMData(u_char *mpp, int XM_ID, int S3MPan) /***************************************************************************** GetLong - Returns a long from given address + Returns a int from given address *****************************************************************************/ -u_long GetLong(u_char *mpp) +u_int GetLong(u_char *mpp) { u_char a; u_char b; u_char c; u_char d; - u_long e; + u_int e; a = *(mpp); b = *(mpp + 1); @@ -1306,7 +1306,7 @@ SetInstr void SetInstr(u_char inst) { - u_long *j; + u_int *j; u_char j2; short ddd; @@ -1344,7 +1344,7 @@ void SetInstr(u_char inst) */ j = mh->JAP_SampHdrAddr[inst]; - if (j == (u_long*)0x01234567) + if (j == (u_int*)0x01234567) return; j2 = *((u_char*)j + 12); @@ -1373,7 +1373,7 @@ SetPer void SetPer(void) { - u_long *j; + u_int *j; u_short period; u_char a; if (CurrentCh > 23) @@ -1749,7 +1749,7 @@ DoVol c Instrument volume *****************************************************************************/ -short DoVol(u_long a,short b,short c) +short DoVol(u_int a,short b,short c) { a*=b; a*=c; @@ -2494,10 +2494,10 @@ GetFreq2 int JPPer = 7350; //6578 -long GetFreq2(long period) +int GetFreq2(int period) { int okt; - long frequency; + int frequency; //FntPrint("period %d\n",period); period = JPPer - period; @@ -2525,7 +2525,7 @@ short ProcessEnvelope(short v,u_char keyon,int JSmp) u_char a2,b; u_short p; -u_long* j; +u_int* j; short apos; short aval; short bpos; @@ -2597,7 +2597,7 @@ short ProcessPanEnvelope(short v, u_char keyon, int JSmp) u_char a2, b; u_short p; - u_long* j; + u_int* j; short apos; short aval; short bpos; diff --git a/src_rebuild/Game/C/xmplay.h b/src_rebuild/Game/C/xmplay.h index 668822ffa..41d5ca130 100644 --- a/src_rebuild/Game/C/xmplay.h +++ b/src_rebuild/Game/C/xmplay.h @@ -45,11 +45,11 @@ typedef struct _XMHEADER { u_short bpm; u_short XMChannels; u_short XMPSXChannels; - u_long *JAP_PAT_ADDR[256]; /* Pattern Start Addresses (maxpatt*chnls)*/ - u_long *JAP_PAT_ADDR2[256]; /* Pattern Start Addresses (maxpatt*chnls)*/ - u_long *JAP_InstrumentOffset[128]; - u_long *JAP_SampAddr[128]; - u_long *JAP_SampHdrAddr[128]; + u_int *JAP_PAT_ADDR[256]; /* Pattern Start Addresses (maxpatt*chnls)*/ + u_int *JAP_PAT_ADDR2[256]; /* Pattern Start Addresses (maxpatt*chnls)*/ + u_int *JAP_InstrumentOffset[128]; + u_int *JAP_SampAddr[128]; + u_int *JAP_SampHdrAddr[128]; u_char jorders[256]; /* list of patterns */ int S3MPanning; } XMHEADER; @@ -63,8 +63,8 @@ typedef struct _XMCHANNEL { short OldRVol; u_short OldPeriod; u_char OldSample; - u_long OldSOff; - u_long SOffset; + u_int OldSOff; + u_int SOffset; u_char nothing; u_char ChDead; u_char panenvflg; /* envelope flag */ @@ -100,7 +100,7 @@ typedef struct _XMCHANNEL { u_char kick2; /* if 1=sample has to be restarted */ u_char sample; /* which sample number (0-31) */ short handle; /* which sample-handle */ - u_long start; /* The start byte index in the sample */ + u_int start; /* The start byte index in the sample */ u_char panning; /* panning position */ u_char pansspd; /* panslide speed */ u_char volume; /* volume (0 - 64) to play the sample at */ @@ -163,8 +163,8 @@ typedef struct _XMSONG { int JBPM; int PCounter; u_short PatSize; - u_long *PatAdr; - u_long *PatAdr2; + u_int *PatAdr; + u_int *PatAdr2; int PlayMask; int SFXNum; XMCHANNEL XM_Chnl[24]; /* max 32 channels per song*/ @@ -231,7 +231,7 @@ typedef struct _XM_HeaderInfo typedef struct _XM_VABInfo { u_char* Address; - u_long Size; + u_int Size; } XM_VABInfo; typedef struct _XM_Feedback @@ -273,7 +273,7 @@ void XM_PlayStop(int Song_ID); // 0x00085DC8 int InitXMData(u_char *mpp, int XM_ID, int S3MPan); // 0x000831B0 -unsigned long GetLong(u_char *mpp); // 0x000869C0 +unsigned int GetLong(u_char *mpp); // 0x000869C0 void XM_OnceOffInit(int PAL); // 0x00085F7C @@ -309,7 +309,7 @@ void DoTremolo(); // 0x000849F0 short DoPan(short envpan, short pan); // 0x00086560 -short DoVol(unsigned long a, short b, short c); // 0x00086538 +short DoVol(unsigned int a, short b, short c); // 0x00086538 void UpdateXMData(); // 0x00086484 @@ -337,7 +337,7 @@ void UpdateHardware(); // 0x00085448 int IntVols(int Vol1, int Vol2); // 0x00086F70 -long GetFreq2(long period); // 0x00086AF0 +int GetFreq2(int period); // 0x00086AF0 short ProcessEnvelope(short v, u_char keyon, int JSmp); // 0x000857A4 diff --git a/src_rebuild/Game/Frontend/FEmain.c b/src_rebuild/Game/Frontend/FEmain.c index 43b107b30..1e1b9e38a 100644 --- a/src_rebuild/Game/Frontend/FEmain.c +++ b/src_rebuild/Game/Frontend/FEmain.c @@ -22,6 +22,259 @@ #include "C/spool.h" #include "C/state.h" +#ifndef PSX + +#include "PsyX/PsyX_render.h" +#include "../utils/targa.h" +#include "../utils/hqfont.h" + +#define HIRES_FONTS + +struct FEFONT_QUAD +{ + float x0, y0, s0, t0; // top-left + float x1, y1, s1, t1; // bottom-right +}; + +TextureID gHiresFEFontTexture = 0; +OUT_FN2RANGE gHiresFEFontRanges[4]; +OUT_FN2INFO gHiresFEFontCharData[4][224]; +int gHiresFEFontRangeCount = 0; + +void InitHiresFEFont() +{ + char namebuffer[64]; + u_char* data; + + // init font2 + if (!gHiresFEFontTexture) + { + gHiresFEFontRangeCount = 0; + + int width, height, bpp; + int x, y; + int size; + FILE* fp; + sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\fefont.fn2"); + FS_FixPathSlashes(namebuffer); + + fp = fopen(namebuffer, "rb"); + if (fp) + { + int i; + + // read fn2 step by step + OUT_FN2HEADER fn2hdr; + fread(&fn2hdr, sizeof(fn2hdr), 1, fp); + + gHiresFEFontRangeCount = fn2hdr.range_count; + for (i = 0; i < fn2hdr.range_count; ++i) + { + fread(&gHiresFEFontRanges[i], sizeof(gHiresFEFontRanges[i]), 1, fp); + fread(gHiresFEFontCharData[i], sizeof(OUT_FN2INFO), gHiresFEFontRanges[i].count, fp); + } + + fclose(fp); + } + + // load TGA file + sprintf(namebuffer, "%s%s", gDataFolder, "GFX\\HQ\\fefont.tga"); + FS_FixPathSlashes(namebuffer); + + if (LoadTGAImage(namebuffer, &data, width, height, bpp)) + { + if (bpp == 32) + { + gHiresFEFontTexture = GR_CreateRGBATexture(HIRES_FONT_SIZE_W, HIRES_FONT_SIZE_H, data); + } + free(data); + } + } +} + +void FEGetHiresBakedQuad(int char_index, float scale, float* xpos, float* ypos, FEFONT_QUAD* q) +{ + float ipw = 1.0f / (float)HIRES_FONT_SIZE_W; + float iph = 1.0f / (float)HIRES_FONT_SIZE_H; + + const OUT_FN2INFO* b = gHiresFEFontCharData[0] + char_index - gHiresFEFontRanges[0].start; + + float fscale = 0.5f * scale; + + float s_x = b->x1 - b->x0; + float s_y = b->y1 - b->y0; + + q->x0 = *xpos + b->xoff * fscale; + q->y0 = *ypos + b->yoff * fscale; + q->x1 = (b->xoff2 - b->xoff) * fscale; + q->y1 = (b->yoff2 - b->yoff) * fscale; + + q->s0 = b->x0 * 255.0f * ipw; + q->t0 = b->y0 * 255.0f * iph; + q->s1 = s_x * 255.0f * ipw; + q->t1 = s_y * 255.0f * iph; + + q->y0 += 32.0f; + + *xpos += b->xadvance * fscale; +} + +void SetHiresFEFontTexture(int enabled) +{ + if (gHiresFEFontTexture == 0) + { + return; + } + + DR_PSYX_TEX* tex = (DR_PSYX_TEX*)current->primptr; + if (enabled) + SetPsyXTexture(tex, gHiresFEFontTexture, 255, 255); + else + SetPsyXTexture(tex, 0, 0, 0); + + addPrim(current->ot + 1, tex); + current->primptr += sizeof(DR_PSYX_TEX); +} + +int FEStringWidthHires(char* string) +{ + char* pString = string; + u_char c = 0; + + int w = 0; + + while ((c = *pString++) != 0) + { + float fx, fy; + fx = 0; + fy = 0; + FEFONT_QUAD q; + FEGetHiresBakedQuad(c, 1.0f, &fx, &fy, &q); + + w += fx; + } + + return w; +} + +int FEPrintStringSizedHires(char* string, int x, int y, int scale, int transparent, int r, int g, int b) +{ + if (current == NULL || string == NULL) + return -1; + + POLY_FT4* shadow; + POLY_FT4* font; + u_char let; + int w; + int h; + + SetHiresFEFontTexture(0); + font = (POLY_FT4*)current->primptr; + + while ((let = *string++) != 0) + { + if (let == '\n') + continue; + + float fx, fy; + fx = x; + fy = y; + FEFONT_QUAD q; + FEGetHiresBakedQuad(let, scale / 4096.0f, &fx, &fy, &q); + + setPolyFT4(font); + setSemiTrans(font, 1); + + setRGB0(font, r, g, b); + setUVWH(font, q.s0, q.t0, q.s1, q.t1); + setXYWH(font, q.x0, q.y0, q.x1, q.y1); + + font->clut = 0; + font->tpage = 0; + + addPrim(current->ot + 1, font); + shadow = font + 1; + + // add shadow poly + memcpy(shadow, font, sizeof(POLY_FT4)); + setRGB0(shadow, 10, 10, 10); + setXYWH(shadow, q.x0 + 1.0f, q.y0 + 1.0f, q.x1, q.y1); + + addPrim(current->ot + 1, shadow); + font += 2; + + // make room for next character + x += fx - x; + } + + // set tail + current->primptr = (char*)font; + SetHiresFEFontTexture(1); + + return x; +} + +int FEPrintStringHires(char* string, float x, float y, int justification, int r, int g, int b) +{ + POLY_FT4* shadow; + POLY_FT4* font; + u_char let; + + if (justification & 4) + { + x -= FEStringWidthHires(string); + } + + SetHiresFEFontTexture(0); + font = (POLY_FT4*)current->primptr; + + int counter = 0; + + while ((let = *string++) != 0) + { + float fx, fy; + fx = x; + fy = y; + FEFONT_QUAD q; + FEGetHiresBakedQuad(let, 1.0f, &fx, &fy, &q); + + setPolyFT4(font); + setSemiTrans(font, 1); + + setRGB0(font, r, g, b); + setUVWH(font, q.s0, q.t0, q.s1, q.t1); + setXYWH(font, q.x0, q.y0, q.x1, q.y1); + + font->clut = 0; + font->tpage = 0; + + addPrim(current->ot + 1, font); + shadow = font + 1; + + // add shadow poly + memcpy(shadow, font, sizeof(POLY_FT4)); + setRGB0(shadow, 10, 10, 10); + setXYWH(shadow, q.x0 + 1.0f, q.y0 + 1.0f, q.x1, q.y1); + + addPrim(current->ot + 1, shadow); + font += 2; + + // add space for next character + x += fx - x; + + if (++counter >= 32) + break; + } + + // set tail + current->primptr = (char *)font; + + SetHiresFEFontTexture(1); + + return x; +} + +#endif // PSX struct PSXBUTTON { @@ -331,8 +584,8 @@ char carNumLookup[4][10] = { int minmaxSelections[4][2] = { { 0, 8 }, - { 8, 17 }, - { 18, 27 }, + { 8, 18 }, + { 18, 28 }, { 28, 37 } }; @@ -566,16 +819,17 @@ void SetVariable(int var) GameType = GAME_IDLEDEMO; gCurrentMissionNumber = (value + 400); break; +#if ENABLE_BONUS_CONTENT case 14: // [A] { ShowBonusGallery(); - LoadFrontendScreens(0); } - case 15: + case 15: // [A] mini cars cheat { ActiveCheats.cheat13 = value; } +#endif } } @@ -702,7 +956,7 @@ void DisplayOnScreenText(void) text = "Incompatible controller in Port 1"; } - FEPrintStringSized(text, 40, 400, 0xc00, transparent, 64, 64, 64); + FEPrintStringSized(text, 40, 400, 3072, transparent, 64, 64, 64); } else { @@ -716,14 +970,14 @@ void DisplayOnScreenText(void) strcat(ScreenTitle, ScreenNames[i]); } - FEPrintStringSized(ScreenTitle, 40, 400, 0xc00, 1, 64, 64, 64); + FEPrintStringSized(ScreenTitle, 40, 400, 3072, 1, 64, 64, 64); } if (iScreenSelect == SCREEN_CUTSCENE) { text = GET_MISSION_TXT(CutSceneNames[cutSelection + CutAmountsTotal[currCity]]); - FEPrintStringSized(text, 100, 226, 0xc00, 1, 64, 64, 64); + FEPrintStringSized(text, 100, 226, 3072, 1, 64, 64, 64); } } } @@ -933,7 +1187,7 @@ void SetupExtraPoly(char *fileName, int offset, int offset2) rect.w = 64; rect.h = 219; - LoadImage(&rect, (u_long *)(_frontend_buffer + offset2 + offset * 0x8000)); + LoadImage(&rect, (u_long*)(_frontend_buffer + offset2 + offset * 0x8000)); DrawSync(0); VSync(0); @@ -1059,20 +1313,21 @@ void LoadFrontendScreens(int full) #ifndef PSX // [A] SCREEN HACKS - + // Time of day extended screen + PsxScreens[3].userFunctionNum = 22; // TimeOfDaySelectScreen +#endif // for web demo content (or empty SCRS.BIN) - if(PsxScreens[0].userFunctionNum == 128) + if (PsxScreens[0].userFunctionNum == 128) PsxScreens[0].userFunctionNum = 23; // DemoScreen - // Time of day extended screen - PsxScreens[3].userFunctionNum = 22; //TimeOfDaySelectScreen - +#ifndef PSX // replay theater PsxScreens[4].buttons[0].action = FE_MAKEVAR(BTN_NEXT_SCREEN, 39); PsxScreens[4].buttons[0].var = -1; - PsxScreens[39].userFunctionNum = 21; // UserReplaySelectScreen +#endif // PSX +#if ENABLE_BONUS_CONTENT // make mini cars cheat screen PsxScreens[40] = PsxScreens[31]; PsxScreens[40].userFunctionNum = 24; // MiniCarsOnOffScreen @@ -1175,7 +1430,7 @@ void ReInitScreens(int returnToMain) NumPlayers = 1; gWantNight = 0; gNight = 0; - gTimeOfDay = 1; + gTimeOfDay = TIME_DAY; gSubGameNumber = 0; feVariableSave[3] = -1; @@ -1197,7 +1452,7 @@ void ReInitScreens(int returnToMain) pCurrScreen = pScreenStack[ScreenDepth]; pNewButton = pButtonStack[ScreenDepth]; - // [A] state hack + // [A] state hack for demo if (pCurrScreen == NULL) pCurrScreen = &PsxScreens[0]; @@ -1552,6 +1807,9 @@ void SetFEDrawMode(void) void InitFrontend(void) { InitCdIcon(); +#ifdef HIRES_FONTS + InitHiresFEFont(); +#endif ResetGraph(1); SetDispMask(0); @@ -1704,9 +1962,15 @@ int FEStringWidth(char* string) { char* pString = string; u_char c = 0; - int w = 0; +#ifdef HIRES_FONTS + if (gHiresFEFontTexture) + { + return FEStringWidthHires(string); + } +#endif + while ((c = *pString++) != 0) { if (c == ' ') @@ -1724,30 +1988,24 @@ int FEPrintString(char *string, int x, int y, int justification, int r, int g, i if (current == NULL || string == NULL) return -1; +#ifdef HIRES_FONTS + if (gHiresFEFontTexture) + { + return FEPrintStringHires(string, x, y, justification, r, g, b); + } +#endif + FE_CHARDATA *pFontInfo; SPRT *font; u_char let; - font = (SPRT *)current->primptr; - if (justification & 4) { - char *pString = string; - u_char c = 0; - - int w = 0; - - while ((c = *pString++) != 0) - { - if (c == ' ') - w += 4; - else - w += feFont.CharInfo[c].w; - } - - x -= w; + x -= FEStringWidth(string); } + font = (SPRT*)current->primptr; + int counter = 0; while ((let = *string++) != 0) @@ -1805,6 +2063,13 @@ int FEPrintStringSized(char *string, int x, int y, int scale, int transparent, i if (current == NULL || string == NULL) return -1; +#ifdef HIRES_FONTS + if (gHiresFEFontTexture) + { + return FEPrintStringSizedHires(string, x, y, scale, transparent, r, g, b); + } +#endif + POLY_FT4 *font; FE_CHARDATA *pFontInfo; u_char let; @@ -1873,10 +2138,10 @@ int CentreScreen(int bSetup) char text[32]; sprintf(text, "X1: %d, Y1: %d", current->disp.screen.x, current->disp.screen.y); - FEPrintStringSized(text, 25, 50, 0xC00, 0, 128, 0, 0); + FEPrintStringSized(text, 25, 50, 3072, 0, 128, 0, 0); sprintf(text, "X2: %d, Y2: %d", last->disp.screen.x, last->disp.screen.y); - FEPrintStringSized(text, 25, 75, 0xC00, 0, 128, 0, 0); + FEPrintStringSized(text, 25, 75, 3072, 0, 128, 0, 0); #endif if (feNewPad & MPAD_CROSS) @@ -1973,9 +2238,17 @@ int CarSelectScreen(int bSetup) { for (int i = 4; i < 9; i++) { +#if USE_PC_FILESYSTEM + // [A] minimal requirement for this car to be selectable + extern int gContentOverride; + if (i == 8) + CarAvailability[0][i] = gContentOverride && FileExists("LEVELS\\CHICAGO\\CARMODEL_11_clean.MDL"); // remove truck + else + CarAvailability[0][i] = 1; +#else if (i != 8) CarAvailability[0][i] = 1; // remove truck - +#endif CarAvailability[1][i] = 1; CarAvailability[2][i] = 1; CarAvailability[3][i] = 1; @@ -2113,7 +2386,7 @@ int CarSelectScreen(int bSetup) } rect = extraRect; - LoadImage(&rect, (u_long *)(_frontend_buffer + carSelection * 0x8000)); + LoadImage(&rect, (u_long*)(_frontend_buffer + carSelection * 0x8000)); DrawSync(0); #ifdef PSX @@ -2223,7 +2496,7 @@ int MissionSelectScreen(int bSetup) for (i = 0; (i < 4) && !done; i++) { if (botch[currMission + i].missNum > gFurthestMission || - currMission + i > minmaxSelections[currCity][1] || + currMission + i >= minmaxSelections[currCity][1] || currMission + i > 36) { done = true; @@ -2505,7 +2778,7 @@ int MissionCityScreen(int bSetup) } rect = extraRect; - LoadImage(&rect, (u_long *)(_frontend_buffer + currCity * 0x8000)); + LoadImage(&rect, (u_long*)(_frontend_buffer + currCity * 0x8000)); DrawSync(0); #ifdef PSX @@ -2725,9 +2998,9 @@ int CutSceneCitySelectScreen(int bSetup) bDrawExtra = 1; if (currCity == 4) - LoadImage(&rect, (u_long *)_frontend_buffer); + LoadImage(&rect, (u_long*)_frontend_buffer); else - LoadImage(&rect, (u_long *)(_frontend_buffer + currCity * 0x8000)); + LoadImage(&rect, (u_long*)(_frontend_buffer + currCity * 0x8000)); DrawSync(0); } @@ -2785,9 +3058,9 @@ int CutSceneCitySelectScreen(int bSetup) rect = extraRect; if (GameLevel != 4) - LoadImage(&rect, (u_long *)(_frontend_buffer + GameLevel * 0x8000)); + LoadImage(&rect, (u_long*)(_frontend_buffer + GameLevel * 0x8000)); else - LoadImage(&rect, (u_long *)_frontend_buffer); + LoadImage(&rect, (u_long*)_frontend_buffer); DrawSync(0); @@ -3182,7 +3455,7 @@ int CityCutOffScreen(int bSetup) bDrawExtra = 1; RECT16 rect = extraRect; - LoadImage(&rect, (u_long *)(_frontend_buffer + currCity * 0x8000)); + LoadImage(&rect, (u_long*)(_frontend_buffer + currCity * 0x8000)); DrawSync(0); } #endif @@ -3231,7 +3504,7 @@ int CityCutOffScreen(int bSetup) } RECT16 rect = extraRect; - LoadImage(&rect, (u_long *)(_frontend_buffer + currCity * 0x8000)); + LoadImage(&rect, (u_long*)(_frontend_buffer + currCity * 0x8000)); DrawSync(0); #endif return 0; @@ -3298,8 +3571,8 @@ static char* cheatText[] = G_LTXT_ID(GTXT_Circuit), G_LTXT_ID(GTXT_Invincibility), G_LTXT_ID(GTXT_Immunity), - G_LTXT_ID(GTXT_MiniCars), // [A] - G_LTXT_ID(GTXT_BonusGallery) // [A] + G_LTXT_ID(GTXT_MiniCars), // [A] + G_LTXT_ID(GTXT_BonusGallery) // [A] }; // [D] [T] @@ -3335,7 +3608,7 @@ int CheatScreen(int bSetup) } if (gFurthestMission == 40) - numOpen = 6; // [A] now 5 elements as "Bonus gallery" is open + numOpen = 4 + ENABLE_BONUS_CONTENT * 2; // [A] now 5 elements as "Bonus gallery" is open else numOpen = AvailableCheats.cheat1 + AvailableCheats.cheat2 + AvailableCheats.cheat3 + AvailableCheats.cheat4; @@ -3472,7 +3745,7 @@ int CheatScreen(int bSetup) pCurrScreen->buttons[4].u = 4; } - // [A] adding bonus gallery + // [A] adding mini cars cheat if (numOpen >= 6) { pCurrScreen->buttons[5].action = hackLookup1[cheatOn[5]]; @@ -3645,7 +3918,8 @@ int BuildButtonsVertical(int count, int xStart, int yStart) #ifndef PSX #include "../utils/fs.h" -char gFEReplayList[8][20]; +#define MAX_REPLAY_NAME_LENGTH 48 +char gFEReplayList[8][MAX_REPLAY_NAME_LENGTH]; int gFEReplayCount = 0; #endif @@ -3664,9 +3938,9 @@ int UserReplaySelectScreen(int bSetup) while (filename) { - strncpy(gFEReplayList[gFEReplayCount], filename, 16); + strncpy(gFEReplayList[gFEReplayCount], filename, MAX_REPLAY_NAME_LENGTH); tmp = strchr(filename, '.'); - gFEReplayList[gFEReplayCount][19] = 0; + gFEReplayList[gFEReplayCount][MAX_REPLAY_NAME_LENGTH-1] = 0; gFEReplayCount++; filename = FS_FindNext(fd); @@ -3690,7 +3964,7 @@ int UserReplaySelectScreen(int bSetup) for (int i = 0; i < numButtons; i++) { PSXBUTTON& btn = pCurrScreen->buttons[i]; - strcpy(btn.Name, gFEReplayList[i]); + strncpy(btn.Name, gFEReplayList[i], sizeof(btn.Name)); tmp = strchr(btn.Name, '.'); @@ -3768,7 +4042,7 @@ int TimeOfDaySelectScreen(int bSetup) { // setup time we want to reset it wantedWeather = 0; - wantedTimeOfDay = 1; + wantedTimeOfDay = TIME_DAY; numButtons = BuildButtonsVertical(3, 168, 208); @@ -3828,7 +4102,7 @@ int TimeOfDaySelectScreen(int bSetup) wantedTimeOfDay += dir; wantedTimeOfDay &= 3; - gWantNight = wantedTimeOfDay == 2 || wantedTimeOfDay == 3; + gWantNight = wantedTimeOfDay == TIME_DUSK || wantedTimeOfDay == TIME_NIGHT; } else if (i == 1) { diff --git a/src_rebuild/Game/dr2limits.h b/src_rebuild/Game/dr2limits.h index 2670d0112..c0361c401 100644 --- a/src_rebuild/Game/dr2limits.h +++ b/src_rebuild/Game/dr2limits.h @@ -4,6 +4,12 @@ // DRIVER 2 game engine limits // please populate this file only with engine limits during refactoring + +#ifndef PSX +#define DYNAMIC_LIGHTING +#define MAX_DLIGHTS 32 +#endif + #ifndef PSX #define MAX_PLAYERS 16 // used for replay streams mostly #else diff --git a/src_rebuild/Game/dr2locale.h b/src_rebuild/Game/dr2locale.h index 6653f7d43..9b351252c 100644 --- a/src_rebuild/Game/dr2locale.h +++ b/src_rebuild/Game/dr2locale.h @@ -68,6 +68,7 @@ enum GameStrId GTXT_FilmDirector, GTXT_QuickReplay, GTXT_Exit, + GTXT_Back, GTXT_Rotation, GTXT_Move, GTXT_SkipCutscene, diff --git a/src_rebuild/Game/dr2math.h b/src_rebuild/Game/dr2math.h index 1cbed3991..eb1567dec 100644 --- a/src_rebuild/Game/dr2math.h +++ b/src_rebuild/Game/dr2math.h @@ -29,7 +29,6 @@ extern short rcossin_tbl[8192]; // math constants #define FixHalfRound(x, bits) (((x) + (1 << (bits-1))) >> bits) -#define FixFloorSigned(x, bits) ((x) / (1 << bits)) // in disassembly: ((int(x) < 0 ? int(x) + (1 << bits)-1 : int(x)) >> bits) #define FIXEDH(a) FixHalfRound(a, ONE_BITS) // Fixed Half Round number #define FIXED(a) ((a) >> ONE_BITS) // Fixed number (unsigned) @@ -40,8 +39,12 @@ extern short rcossin_tbl[8192]; #define isin(a) (rcossin_tbl[( ( a ) & 4095) * 2]) #define icos(a) (rcossin_tbl[((( a )+1024) & 4095) * 2]) -#define DIFF_ANGLES( A, B ) \ - (((((B) - (A)) + 2048) & 4095) - 2048) +#define RAND(seed) ((seed) * 0x19660D + 0x3C6EF35F) + +#define DIFF_ANGLES_R( A, B, RANGE ) \ + (((((B) - (A)) + (RANGE>>1)) & RANGE-1) - (RANGE>>1)) + +#define DIFF_ANGLES( A, B ) DIFF_ANGLES_R(A, B, 4096) // Remap a value in the range [A,B] to [C,D]. #define RemapVal( val, A, B, C, D) \ @@ -133,6 +136,14 @@ extern short rcossin_tbl[8192]; #define MAX(a,b) fst_max(a,b) #endif +#ifdef PSX +#undef ABS // don't use PsyQ's silly ABS that might not be optimized +#endif + +#ifndef ABS +#define ABS(a) fst_abs(a) +#endif + inline int fst_min(int a, int b) { int diff = a - b; @@ -147,4 +158,10 @@ inline int fst_max(int a, int b) return a - (diff & dsgn); } +inline int fst_abs(int x) +{ + int mask = x >> 31; + return (x ^ mask) - mask; +} + #endif // DR2MATH_H \ No newline at end of file diff --git a/src_rebuild/Game/dr2types.h b/src_rebuild/Game/dr2types.h index eba624f9e..390def56a 100644 --- a/src_rebuild/Game/dr2types.h +++ b/src_rebuild/Game/dr2types.h @@ -9,10 +9,10 @@ typedef short SHORTVECTOR4[4]; -typedef long LONGVECTOR3[3]; -typedef long LONGVECTOR4[4]; +typedef int LONGVECTOR3[3]; +typedef int LONGVECTOR4[4]; -typedef long LONGQUATERNION[4]; +typedef int LONGQUATERNION[4]; struct VECTOR2 { @@ -291,16 +291,6 @@ struct HUBCAP int Duration; }; -struct BOUND_BOX -{ - int x0; - int y0; - int z0; - int x1; - int y1; - int z1; -}; - typedef struct _HANDLING_TYPE { char frictionScaleRatio; @@ -362,7 +352,7 @@ typedef struct _HANDLING_DATA union RigidBodyState { - long v[13]; + int v[13]; struct { LONGVECTOR3 fposition; LONGQUATERNION orientation; @@ -762,7 +752,7 @@ typedef struct _TARGET int eventId; // data 3 union { - VECTOR* eventPos; // data 4 + int eventPos; // data 4 int unused[10]; }; int loseMessage; // data 14 @@ -772,7 +762,7 @@ typedef struct _TARGET }; } MS_TARGET; -assert_sizeof(MS_TARGET, 64); +static_assert(sizeof(MS_TARGET) == 64, "MS_TARGET size is not correct"); //--------------------------------------------------------------------------------------- @@ -1155,24 +1145,6 @@ struct ROADBLOCK //--------------------------------------------------------------------------------------- // TODO: OBJCOLL.H -struct tRay -{ - LONGVECTOR4 org; - LONGVECTOR4 dir; -}; - -struct tRange -{ - int lower; - int upper; -}; - -struct tAABB -{ - tRange slab[3]; -}; - - struct TestResult { int depth; @@ -1346,4 +1318,21 @@ enum GAMEMODE GAMEMODE_DEMO = 6, }; +//--------------------------------------------------- + +enum TIMEOFDAY +{ + TIME_DAWN = 0, + TIME_DAY = 1, + TIME_DUSK = 2, + TIME_NIGHT = 3 +}; + +enum WEATHER +{ + WEATHER_NONE = 0, + WEATHER_RAIN = 1, + WEATHER_WET = 2 +}; + #endif // DR2TYPES_H \ No newline at end of file diff --git a/src_rebuild/Game/driver2.h b/src_rebuild/Game/driver2.h index 0cd5668ee..e9fc5ce6f 100644 --- a/src_rebuild/Game/driver2.h +++ b/src_rebuild/Game/driver2.h @@ -26,8 +26,12 @@ #include "platform.h" -#define USE_PC_FILESYSTEM (!defined(PSX)) // PC filesystem is prioritized over CD -#define USE_CD_FILESYSTEM 1 // use always +#define USE_PC_FILESYSTEM (!defined(PSX)) // PC filesystem is prioritized over CD +#define USE_CD_FILESYSTEM 1 // use always +#define ENABLE_MISSION_FIXES 1 +#define ENABLE_GAME_FIXES 1 +#define ENABLE_GAME_ENCHANCEMENTS 1 +#define ENABLE_BONUS_CONTENT 1 #ifdef PSX // TODO: Include PSX STUFF diff --git a/src_rebuild/Game/engine/mdl.h b/src_rebuild/Game/engine/mdl.h index 9ee02a21a..8d552de82 100644 --- a/src_rebuild/Game/engine/mdl.h +++ b/src_rebuild/Game/engine/mdl.h @@ -160,26 +160,6 @@ struct MODEL int normals; int point_normals; int collision_block; - - SVECTOR* pVertex(int i) const - { - return (SVECTOR *)(((u_char *)this) + vertices) + i; - } - - SVECTOR* pNormal(int i) const - { - return (SVECTOR *)(((u_char *)this) + point_normals) + i; - } - - COLLISION_PACKET* pCollisionPacket(int i) const - { - return (COLLISION_PACKET *)(((u_char *)this) + collision_block) + i; - } - - char* pPolyAt(int ofs) const - { - return (char *)(((u_char *)this) + poly_block + ofs); - } }; diff --git a/src_rebuild/Game/psyx_compat.h b/src_rebuild/Game/psyx_compat.h index 9aa47c7f5..f487223b5 100644 --- a/src_rebuild/Game/psyx_compat.h +++ b/src_rebuild/Game/psyx_compat.h @@ -7,6 +7,8 @@ #ifndef PSX #include "PsyX/PsyX_public.h" #include "PsyX/PsyX_globals.h" +#include "psx/libgte.h" +#include "psx/libgpu.h" #endif // Necessary types diff --git a/src_rebuild/Game/reversing.h b/src_rebuild/Game/reversing.h index fb4759602..09ed9489a 100644 --- a/src_rebuild/Game/reversing.h +++ b/src_rebuild/Game/reversing.h @@ -14,6 +14,8 @@ #define M_INT_4(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d) ) #define M_INT_4R(a,b,c,d) M_INT_4(d, c, b, a) +#define M_BIT(x) (1 << (x)) + //--------------------------------------- #if !defined( __TYPEINFOGEN__ ) && !defined( _lint ) && defined(_WIN32) // pcLint has problems with assert_offsetof() diff --git a/src_rebuild/Game/version.h b/src_rebuild/Game/version.h index 88dbe0192..9087f4a4b 100644 --- a/src_rebuild/Game/version.h +++ b/src_rebuild/Game/version.h @@ -1,9 +1,9 @@ #ifndef GAME_VERSION_N -#define GAME_VERSION_N "7.4" +#define GAME_VERSION_N "7.8" #endif #ifndef GAME_VERSION_RES -#define GAME_VERSION_RES 7,4 +#define GAME_VERSION_RES 7,8 #endif #define GAME_TITLE "REDRIVER2" diff --git a/src_rebuild/PsyCross b/src_rebuild/PsyCross index 502f700c5..b086bba2a 160000 --- a/src_rebuild/PsyCross +++ b/src_rebuild/PsyCross @@ -1 +1 @@ -Subproject commit 502f700c5ba88b1ee0f7bca5cdd8ea66b833417a +Subproject commit b086bba2a20a6208e8f5272b38357717de01eb17 diff --git a/src_rebuild/platform/Emscripten/shell.html b/src_rebuild/platform/Emscripten/shell.html index df805bb6f..0716477a5 100644 --- a/src_rebuild/platform/Emscripten/shell.html +++ b/src_rebuild/platform/Emscripten/shell.html @@ -86,9 +86,8 @@ - - emscripten + Downloading... @@ -107,97 +106,88 @@ - + - {{{ SCRIPT }}} + {{{ SCRIPT }}}
Driver 2 Playstation game reverse engineering effort
Reverse-Engineered version of Driver 2. https://opendriver2.github.io