Compare commits

...

85 Commits

Author SHA1 Message Date
mark wallace
d0ea5f41be - Added static const int DUCK_DELAY_FRAMES = 30 to define the delay (1 second at 30 FPS).
- Added `int duckFrameCounter` to track frames the duck button is held.
  - Added `bool isDucking` to track crouch state and prevent re-triggering.
  - Updated `CPad` constructor to initialize `duckFrameCounter` and `isDucking`.
2025-03-30 18:37:55 +00:00
mark wallace
f7d23f3bb3 Modified CPad::DuckJustDown to use a frame counter for a 1-second delay. 2025-03-30 18:35:13 +00:00
Stefanos Kornilios Mitsis Poiitidis
24114d9a07 Merge branch 'falco/miami_settings_saving' into 'main'
Miami Settings Save File + Miami/Liberty Settings Icons

See merge request skmp/dca3-game!88
2025-03-30 09:31:19 +00:00
Stefanos Kornilios Mitsis Poiitidis
df7e4439d1 Merge branch 'falco/location_ui_string_positioning' into 'main'
Moved HUD location label up to align with minimap.

See merge request skmp/dca3-game!89
2025-03-30 09:22:00 +00:00
Stefanos Kornilios Mitsis Poiitidis
d83ae53746 Fix liberty 0GDTEX rule 2025-03-30 12:16:45 +03:00
Falco Girgis
4178d6f8f0 Moved HUD location label up to align with minimap.
Users were complaining that the location HUD strings were appearing too
low onscreen and were getting cut-off on certain CRTs and that the
placement of this text does not match that of the PS2 version and looks
janky.

This PR simply moves it up vertically to align with the bottom of the
Radar guage so that it doesn't get cut off and matches the relative
positioning of the PS2 version, which people seem to like better.
2025-03-30 04:10:16 -05:00
Falco Girgis
5914842483 Addressed review feedback. 2025-03-30 03:54:01 -05:00
Falco Girgis
a6facaec30 Merge branch 'thegang/vmu-icons' into falco/miami_settings_saving 2025-03-30 01:01:19 -05:00
Stefanos Kornilios Mitsis Poiitidis
eea56cb195 Merge branch 'ph3nom/miami-allow-reduced-draw-distance-mr' into 'main'
Allow Draw Distance Slider to Go Lower than Default Limit

See merge request skmp/dca3-game!87
2025-03-30 05:36:47 +00:00
Stefanos Kornilios Mitsis Poiitidis
968922b0d7 Merge branch 'ph3nom/reduced-rain-mr' into 'main'
Rain Sprites are Fillrate Constrained on PVR GPU.  Reduce Layers for DC Build.

See merge request skmp/dca3-game!86
2025-03-30 05:35:47 +00:00
Falco Girgis
b1b225b345 Added basic settings.ini saving to Miami. 2025-03-29 22:53:49 -05:00
Josh Pearson
d240a6d33f Allow Draw Distance Slider to Go Lower than Default Limit
Will allow users to opt for better performance with reduced draw distance, if desired
2025-03-29 10:33:52 -06:00
Josh Pearson
a584cee0cc Rain Sprites are Fillrate Constrained on PVR GPU. Reduce Layers for DC Build. 2025-03-29 10:31:09 -06:00
Stefanos Kornilios Mitsis Poiitidis
9da3c4b076 Merge branch 'skmp/gta3-folder-is-liberty' into 'main'
liberty: now uses ../../liberty and ../../liberty_mod for source assets

See merge request skmp/dca3-game!85
2025-03-29 14:57:43 +00:00
Stefanos Kornilios Mitsis Poiitidis
59a75bf12b Merge branch 'skmp/fix-stream-volume-fades' into 'main'
streams: Update volumes on SetMusicMasterVolume/SetMusicFadeVolume

See merge request skmp/dca3-game!84
2025-03-29 14:48:38 +00:00
Stefanos Kornilios Mitsis Poiitidis
62dbf132c1 liberty: now uses ../../liberty and ../../liberty_mod for source assets 2025-03-29 16:45:00 +02:00
Stefanos Kornilios Mitsis Poiitidis
82bc55c3d4 streams: Update volumes on SetMusicMasterVolume/SetMusicFadeVolume 2025-03-29 16:37:20 +02:00
Stefanos Kornilios Mitsis Poiitidis
2cb15f3728 Merge branch 'skmp/streaming-and-sfx-fixes' into 'main'
streaming: Fix prefetch behaviour, read discards race, sfx and stream playback position race

See merge request skmp/dca3-game!83
2025-03-29 14:33:26 +00:00
Stefanos Kornilios Mitsis Poiitidis
9eace08c7e streaming: Fix prefetch behaviour, read discards race, sfx and stream playback position race 2025-03-29 16:23:44 +02:00
Stefanos Kornilios Mitsis Poiitidis
0657700e11 Merge branch 'falco/collision_sh4_accel_phase1' into 'main'
Collision Acceleration Part 1

See merge request skmp/dca3-game!77
2025-03-29 09:23:31 +00:00
Falco Girgis
6c71054cb4 Addressed review feedback. 2025-03-28 17:50:59 -05:00
Stefanos Kornilios Mitsis Poiitidis
99431370a2 Merge branch 'skmp/liberty-remove-menumap' into 'main'
liberty: remove menu map as it leads to texoom

See merge request skmp/dca3-game!82
2025-03-28 20:27:35 +00:00
Stefanos Kornilios Mitsis Poiitidis
d240d3ba68 Merge branch 'skmp/24-bpp' into 'main'
Add experimental 24bpp video mode

See merge request skmp/dca3-game!81
2025-03-28 20:21:14 +00:00
Stefanos Kornilios Mitsis Poiitidis
a3a610d8ee liberty: remove menu map as it leads to texoom 2025-03-28 22:17:53 +02:00
Stefanos Kornilios Mitsis Poiitidis
446182f159 Fix sim build 2025-03-28 21:59:25 +02:00
Stefanos Kornilios Mitsis Poiitidis
5ef077fa14 Add experimental 24bpp video mode 2025-03-28 21:56:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
6b41a458c5 Merge branch 'skmp/fix-miami-flamethrower' into 'main'
flamethrower fix for miami

See merge request skmp/dca3-game!80
2025-03-28 19:41:57 +00:00
Stefanos Kornilios Mitsis Poiitidis
fbfb684425 flamethrower fix for miami 2025-03-28 21:28:41 +02:00
Stefanos Kornilios Mitsis Poiitidis
e97d96c6ad Merge branch 'skmp/emufix-and-kosupdate' into 'main'
pvr overflown detection: workaround for emulators; kos update

See merge request skmp/dca3-game!79
2025-03-28 19:23:30 +00:00
Stefanos Kornilios Mitsis Poiitidis
375b507cd8 pvr overflown detection: workaround for emulators; kos update 2025-03-28 21:06:52 +02:00
Stefanos Kornilios Mitsis Poiitidis
c7c4e42f40 Merge branch 'NaiSan/FixCoverSize' into 'main'
Updating images size to 256x256.

See merge request skmp/dca3-game!78
2025-03-28 19:04:20 +00:00
NaiSan89
aa115cdbf6 Updating images size to 256x256. 2025-03-28 08:58:30 -03:00
Falco Girgis
f495bffd00 Addressed review feedback. 2025-03-28 06:24:56 -05:00
Falco Girgis
dec63c5bff Another try at fixing Miami sim builds. 2025-03-28 01:08:58 -05:00
Falco Girgis
3cfdb3c931 Attempt to fix Miami sim builds. 2025-03-28 00:49:14 -05:00
Falco Girgis
374141eda1 Trying again to fix builds: CMatrix constructor. 2025-03-28 00:33:52 -05:00
Falco Girgis
41e544c0f1 Fixed bug with jumping infinitely + sim builds 2025-03-28 00:29:36 -05:00
Falco Girgis
0ba1c595cd Acceleration working in miami. 2025-03-28 00:17:25 -05:00
Falco Girgis
02799207ed Fixed fuck up. 2025-03-27 23:05:15 -05:00
Falco Girgis
687a9ab137 Forgot to remove a micro optimization. 2025-03-27 23:03:39 -05:00
Falco Girgis
3a342b2a9c DCA Liberty working minimal changes. 2025-03-27 22:48:55 -05:00
Stefanos Kornilios Mitsis Poiitidis
cc07dc3c52 Merge branch 'revert-95384c1d' into 'main'
Revert "Merge branch 'skmp/fix-makefile-cases' into 'main'"

See merge request skmp/dca3-game!76
2025-03-26 07:34:16 +00:00
Stefanos Kornilios Mitsis Poiitidis
325f903186 Revert "Merge branch 'skmp/fix-makefile-cases' into 'main'"
This reverts merge request !75
2025-03-26 07:24:47 +00:00
Stefanos Kornilios Mitsis Poiitidis
95384c1d0d Merge branch 'skmp/fix-makefile-cases' into 'main'
Make Audio stream path case insensitive

See merge request skmp/dca3-game!75
2025-03-25 19:07:42 +00:00
Stefanos Kornilios Mitsis Poiitidis
5e690010fd Make Audio stream path case insensitive 2025-03-25 20:58:26 +02:00
Stefanos Kornilios Mitsis Poiitidis
6dcf028717 Merge branch 'skmp/add-0gdtex.pvr' into 'main'
Add 0GDTEX.PVRs

Closes #44

See merge request skmp/dca3-game!74
2025-03-25 18:48:27 +00:00
Stefanos Kornilios Mitsis Poiitidis
3d176a239a Add 0GDTEX.PVRs 2025-03-25 20:39:07 +02:00
Stefanos Kornilios Mitsis Poiitidis
6eba303fb0 Merge branch 'skmp/oom-mitigation-3' into 'main'
Memory usage improvements and memleak fixes

See merge request skmp/dca3-game!72
2025-03-25 18:07:56 +00:00
Stefanos Kornilios Mitsis Poiitidis
cfaab31a71 Small fix for move_only_function. Can't trust ai fully yet hah 2025-03-25 19:55:41 +02:00
Stefanos Kornilios Mitsis Poiitidis
0f3929a3b0 Don't spam print on texconv 2025-03-25 19:49:06 +02:00
Stefanos Kornilios Mitsis Poiitidis
f2e2ff8a29 relax overzealous assert in setCurrentAnim 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
4a336c7a1a pack for less waste 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
fbce6234fe rwdc: Switch to context pointers instead of context offsets 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
5984c4f432 CutsceneHead: Don't leak RpHAnimAnimations 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
1c12637506 ColModel / Triangle planes: more fixes for miami and liberty 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
3b7f5cffc3 collision fixes: fix miami linked list corruption, liberty replica 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
aba5bdac62 fix memleaks and clang 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
19debfced6 im2d: strip -> fan, rwdc micro wins for memory 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
020fe7b5b5 Introduce chunked_vector, it has some more overhead than needed but lets see if it helps 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
7e7d7de546 move save/load compression to allocate with re3StreamingAlloc, assert to make sure allocation worked 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
0f34808e8c Introduce re3StreamingAlloc that tries to despawn if alloc fails, use it for allocs during loading 2025-03-25 19:19:51 +02:00
Stefanos Kornilios Mitsis Poiitidis
ad0e0ac6fb Merge branch 'pgta/ControllerMappingPt2' into 'main'
Pgta/controller mapping pt2

See merge request skmp/dca3-game!71
2025-03-25 17:07:27 +00:00
Stefanos Kornilios Mitsis Poiitidis
c1f9cea93c Merge branch 'Texture_fixes' into 'main'
Texture fixes

See merge request skmp/dca3-game!57
2025-03-25 17:06:28 +00:00
Stefanos Kornilios Mitsis Poiitidis
44cd7935b8 Merge branch 'skmp/update-kos-maple-hotfix' into 'main'
dca3-kos: Update for maple hotfixes

See merge request skmp/dca3-game!73
2025-03-25 14:54:58 +00:00
Stefanos Kornilios Mitsis Poiitidis
c82f4f0998 dca3-kos: Update for maple hotfixes 2025-03-25 16:45:36 +02:00
mark wallace
2fb88c56ef Cleaned up previous button binding MR for A & B buttons, added audible feedback for camera view changes. 2025-03-25 00:05:28 +00:00
mark wallace
bcba2f1eae change camera sound 2025-03-22 05:26:15 +00:00
mark wallace
13ff64119c A+B mapped for Ammu-nation and other things.... 2025-03-21 23:20:52 +00:00
Falco Girgis
1e069ec895 Updated desc + app ID fields for settings file. 2025-03-16 16:56:06 -05:00
Falco Girgis
1a4b84869a Fixed simulator builds by using the regular path. 2025-03-16 13:31:21 -05:00
Falco Girgis
fd7f44e7c2 Adjusted Makefile to only care about settings.ico. 2025-03-16 13:02:19 -05:00
Falco Girgis
6bd5a124cd Forgot to add actual icon. 2025-03-16 12:59:53 -05:00
Falco Girgis
b739b89fd6 Fixing issues with previous merge. 2025-03-16 12:57:52 -05:00
Falco Girgis
6d67dc2ffd Merge remote-tracking branch 'origin/main' into HEAD 2025-03-16 12:49:21 -05:00
Falco Girgis
a7d85c2f7d Settings file saving/loading finalized. 2025-03-16 12:17:09 -05:00
Falco Girgis
2365fe663b Working saving, not loading. 2025-03-16 10:23:55 -05:00
Esppiral V
38c78d0151 luigiineerclub deleted from PT list. 2025-03-16 13:14:19 +00:00
Esppiral V
e07a46a372 Edit FileLoader Miami, removing duplicates adding more textures. 2025-03-16 12:42:12 +00:00
Esppiral V
9c0fd4fd67 Edit FileLoader LIBERTY 2025-03-16 12:39:12 +00:00
Esppiral V
23031096c2 Fix formating errors. 2025-03-13 22:11:37 +00:00
Esppiral V
dde656e932 More textures added 2025-03-13 21:32:57 +00:00
Esppiral V
95a090df77 Edit FileLoader.cpp 2025-03-13 21:30:40 +00:00
Esppiral V
30e7db4b85 Fixes for Miami 2025-03-13 20:48:01 +00:00
Esppiral V
3b3cad4443 Fixes for double sided and PT textures 2025-03-13 20:16:07 +00:00
Stefanos Kornilios Mitsis Poiitidis
6d73e6e79d vmu icon wip 2024-12-29 20:59:26 +02:00
66 changed files with 2977 additions and 1079 deletions

View File

@@ -15,16 +15,16 @@ IS_MAC := $(shell uname -s | grep -i "darwin" > /dev/null && echo "yes" || echo
MOD_NAME?=
GTA_DIR?=../../gta3
GTA_DIR?=../../liberty
GTA_GAMEFILES_LOOSE_DIR?=../gamefiles/liberty
GTA_MOD_DIR?=../../gta3_mod$(MOD_NAME)
GTA_MOD_DIR?=../../liberty_mod$(MOD_NAME)
GTA_MOD_IMG_DIR?=$(GTA_MOD_DIR)/img
GTA_MOD_CUTS_DIR=$(GTA_MOD_DIR)/cuts
GTA_MOD_SFX_DIR?=$(GTA_MOD_DIR)/sfx
GTA_MOD_LOOSE_DIR?=$(GTA_MOD_DIR)/loose
REPACK_DIR?=repack-data
REPACK_GTA_DIR?=$(REPACK_DIR)/gta3
REPACK_GTA_DIR?=$(REPACK_DIR)/liberty
REPACK_IMG_ORIG_DIR?=$(REPACK_DIR)/img-orig
REPACK_IMG_DC_DIR?=$(REPACK_DIR)/img-dc
REPACK_SFX_ORIG_DIR?=$(REPACK_DIR)/sfx-orig
@@ -183,6 +183,14 @@ $(REPACK_GTA_DIR)/GTA3SF8.b: assets/GTA3SF8.b
mkdir -p $(@D)
cp $< $@
$(REPACK_GTA_DIR)/0GDTEX.PVR: assets/0GDTEX.PVR
mkdir -p $(@D)
cp $< $@
$(REPACK_GTA_DIR)/%.ico: assets/%.ico
mkdir -p $(@D)
cp $< $@
1ST_READ.BIN: $(TARGET)
rm -f $(TARGET).bin
rm -f 1ST_READ.BIN
@@ -198,20 +206,20 @@ IP.BIN:
rm -f IP.BIN
$(KOS_BASE)/utils/makeip/makeip ip.txt IP.BIN
$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME).iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ.BIN $(REPACK_GTA_DIR)
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR)
$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTA3SF8.b
$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME)-no-repack.iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ.BIN $(REPACK_GTA_DIR)
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME)-no-repack.iso $(REPACK_GTA_DIR)
$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME).ds.iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp $(TARGET).bin $(REPACK_GTA_DIR)/1ST_READ.BIN
@@ -222,7 +230,7 @@ $(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_
$(KOS_BASE)/utils/scramble/scramble $(TARGET)-prebuilt.bin 1ST_READ_PREBUILT.BIN
mkdir -p $(REPACK_GTA_DIR)
$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ_PREBUILT.BIN $(REPACK_GTA_DIR)/1ST_READ.BIN
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR)
@@ -241,15 +249,15 @@ $(PROJECT_NAME)-prebuilt.cdi: $(PROJECT_NAME)-prebuilt.iso
rm 1ST_READ_PREBUILT.BIN
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
else
$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTA3SF8.b
$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME)-no-repack.cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
endif
@@ -310,7 +318,10 @@ streamheaderpack: ../src/tools/streamheaderpack.cpp
TXD_OPTS_fonts = 256 256
TXD_OPTS_hud = 128 128
TXD_OPTS_menu = 512 512
TXD_OPTS_menu = 512 512 \
--delete-tex mapTop03 --delete-tex mapTop02 --delete-tex mapTop01 \
--delete-tex mapMid03 --delete-tex mapMid02 --delete-tex mapMid01 \
--delete-tex mapBot03 --delete-tex mapBot02 --delete-tex mapBot01
TXD_OPTS_LOADSC0 = 512 512
TXD_OPTS_LOADSC1 = 512 512
TXD_OPTS_LOADSC10 = 512 512

BIN
liberty/assets/0GDTEX.PVR Normal file

Binary file not shown.

BIN
liberty/assets/0GDTEX.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
liberty/assets/settings.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@@ -118,6 +118,7 @@ OBJS_NO_FAST_MATH = \
../src/miami/core/Cam.o \
../src/miami/core/Camera.o \
../src/miami/vehicles/Bike.o \
../src/miami/vehicles/Boat.o \
../src/miami/renderer/Particle.o
KOS_CPPFLAGS += -fbuiltin -ffast-math -ffp-contract=fast \
@@ -182,7 +183,15 @@ $(TARGET): $(OBJS)
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
$(REPACK_GTA_DIR)/GTAVCSF8.b: GTAVCSF8.b
$(REPACK_GTA_DIR)/GTAVCSF8.b: assets/GTAVCSF8.b
mkdir -p $(@D)
cp $< $@
$(REPACK_GTA_DIR)/0GDTEX.PVR: assets/0GDTEX.PVR
mkdir -p $(@D)
cp $< $@
$(REPACK_GTA_DIR)/%.ico: assets/%.ico
mkdir -p $(@D)
cp $< $@
@@ -201,20 +210,20 @@ IP.BIN:
rm -f IP.BIN
$(KOS_BASE)/utils/makeip/makeip ip.txt IP.BIN
$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME).iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ.BIN $(REPACK_GTA_DIR)
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR)
$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTAVCSF8.b
$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME)-no-repack.iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ.BIN $(REPACK_GTA_DIR)
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME)-no-repack.iso $(REPACK_GTA_DIR)
$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(PROJECT_NAME).ds.iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp $(TARGET).bin $(REPACK_GTA_DIR)/1ST_READ.BIN
@@ -225,7 +234,7 @@ $(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_
$(KOS_BASE)/utils/scramble/scramble $(TARGET)-prebuilt.bin 1ST_READ_PREBUILT.BIN
mkdir -p $(REPACK_GTA_DIR)
$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp 1ST_READ_PREBUILT.BIN $(REPACK_GTA_DIR)/1ST_READ.BIN
mkisofs -C 0,11702 -V $(PROJECT_NAME) -G IP.BIN -r -J -l -o $(PROJECT_NAME).iso $(REPACK_GTA_DIR)
@@ -244,15 +253,15 @@ $(PROJECT_NAME)-prebuilt.cdi: $(PROJECT_NAME)-prebuilt.iso
rm 1ST_READ_PREBUILT.BIN
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
else
$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTAVCSF8.b
$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME)-no-repack.cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
mkdcdisc -e $(TARGET) -o $(PROJECT_NAME).cdi -d $(REPACK_GTA_DIR)/ $(MKDCDISC_PAD_OPTION) -n $(PROJECT_NAME) -a $(TEAM_NAME) -s $(DISC_SERIAL) -r $(RELEASE_DATE)
@echo && echo && echo "*** CDI Baked Successfully ($@) ***" && echo && echo
endif

BIN
miami/assets/0GDTEX.PVR Normal file

Binary file not shown.

BIN
miami/assets/0GDTEX.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
miami/assets/settings.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

View File

@@ -11,6 +11,8 @@
#include "AnimBlendAssocGroup.h"
#include "AnimManager.h"
void* re3StreamingAlloc(size_t size);
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
int32 CAnimManager::ms_numAnimBlocks;
@@ -837,7 +839,7 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
uint16_t flags;
CFileMgr::Read(fd, (char*)&flags, sizeof(flags));
seq->keyFrames = RwMalloc(dataSize);
seq->keyFrames = re3StreamingAlloc(dataSize);
assert(seq->keyFrames);
CFileMgr::Read(fd, (char*)seq->keyFrames, dataSize - sizeof(flags));
seq->type = flags;

View File

@@ -173,6 +173,7 @@ public:
char GetCDAudioDriveLetter (void);
void UpdateEffectsVolume(void);
void UpdateStreamsVolume(void);
#ifdef DC_SH4
void UpdateChannelVolume(uint32 nChannel);

View File

@@ -11,6 +11,8 @@
#include "crossplatform.h"
#if !defined(AUDIO_OAL) && !defined(AUDIO_MSS)
#define syncf(...) // dbglog(DBG_CRITICAL, __VA_ARGS__)
#define streamf(...) // dbglog(DBG_CRITICAL, __VA_ARGS__)
#define verbosef(...) // dbglog(DBG_CRITICAL, __VA_ARGS__)
#define debugf(...) // dbglog(DBG_CRITICAL, __VA_ARGS__)
@@ -47,6 +49,8 @@
/* Quick access to the AICA channels */
#define AICA_CHANNEL(x) (AICA_MEM_CHANNELS + (x) * sizeof(aica_channel_t))
static uint32_t chn_version[64];
int aica_play_chn(int chn, int size, uint32_t aica_buffer, int fmt, int vol, int pan, int loop, int freq) {
// assert(size <= 65534);
// We gotta fix this at some point
@@ -70,6 +74,7 @@ int aica_play_chn(int chn, int size, uint32_t aica_buffer, int fmt, int vol, int
chan->freq = freq;
chan->vol = vol;
chan->pan = pan;
chan->version = ++chn_version[chn];
snd_sh4_to_aica(tmp, cmd->size);
return chn;
}
@@ -175,6 +180,12 @@ file_t fdPedSfx;
volatile uint32 nPedSfxReqReadId = 1;
volatile uint32 nPedSfxReqNextId = 1;
// this is very wasteful and temporary
#define BANK_STAGE_SIZE 16 * 2048
static uint8_t stagingBufferBank[BANK_STAGE_SIZE] __attribute__((aligned(32)));
std::mutex stagingBufferMtx;
static int32 DCStreamedLength[TOTAL_STREAMED_SOUNDS];
struct WavHeader {
@@ -357,6 +368,13 @@ cSampleManager::Initialise(void)
if (channels[i].ch != -1) {
assert(channels[i].nSfx != -1);
uint32_t channel_version = g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(channels[i].ch) + offsetof(aica_channel_t, version));
if (chn_version[channels[i].ch] != channel_version) {
syncf("Stream version missmatch, skipping update. expected %d got %d\n", chn_version[channels[i].ch], channel_version);
continue;
}
uint16_t channel_pos = (g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(channels[i].ch) + offsetof(aica_channel_t, pos)) & 0xffff);
// verbosef("Channel %d pos: %d\n", i, channel_pos);
if (!channels[i].loop) {
@@ -383,21 +401,28 @@ cSampleManager::Initialise(void)
{
std::lock_guard<std::mutex> lk(streams[i].mtx);
if (streams[i].playing) {
uint32_t channel_version = g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(streams[i].mapped_ch[0]) + offsetof(aica_channel_t, version));
if (chn_version[streams[i].mapped_ch[0]] != channel_version) {
syncf("Stream version missmatch, skipping update. expected %d got %d\n", chn_version[streams[i].mapped_ch[0]], channel_version);
continue;
}
// get channel pos
uint32_t channel_pos = g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(streams[i].mapped_ch[0]) + offsetof(aica_channel_t, pos)) & 0xffff;
uint32_t logical_pos = channel_pos;
if (logical_pos > STREAM_CHANNEL_SAMPLE_COUNT/2) {
logical_pos -= STREAM_CHANNEL_SAMPLE_COUNT/2;
}
verbosef("Stream %d pos: %d, log: %d, rem: %d\n", i, channel_pos, logical_pos, streams[i].played_samples);
streamf("Stream %d pos: %d, log: %d, played: %d\n", i, channel_pos, logical_pos, streams[i].played_samples);
bool can_refill = (streams[i].played_samples + STREAM_CHANNEL_SAMPLE_COUNT/2) < streams[i].total_samples;
bool can_fetch = (streams[i].played_samples + STREAM_CHANNEL_SAMPLE_COUNT/2 + STREAM_CHANNEL_SAMPLE_COUNT/2 + STREAM_CHANNEL_SAMPLE_COUNT/2) < streams[i].total_samples;
bool can_refill = (streams[i].played_samples + STREAM_CHANNEL_SAMPLE_COUNT/2 + (!streams[i].first_refill)*STREAM_CHANNEL_SAMPLE_COUNT/2) < streams[i].total_samples;
bool can_fetch = (streams[i].played_samples + STREAM_CHANNEL_SAMPLE_COUNT/2 + STREAM_CHANNEL_SAMPLE_COUNT/2 + (!streams[i].first_refill)*STREAM_CHANNEL_SAMPLE_COUNT/2) < streams[i].total_samples;
// copy over data if needed from staging
if (channel_pos >= STREAM_CHANNEL_SAMPLE_COUNT/2 && !streams[i].next_is_upper_half) {
streams[i].next_is_upper_half = true;
if (can_refill) { // could we need a refill?
verbosef("Filling channel %d with lower half\n", i);
streamf("Filling channel %d with lower half\n", i);
// fill lower half
spu_memload(streams[i].aica_buffers[0], streams[i].buffer, STREAM_CHANNEL_BUFFER_SIZE/2);
if (streams[i].stereo) {
@@ -413,7 +438,7 @@ cSampleManager::Initialise(void)
} else if (channel_pos < STREAM_CHANNEL_SAMPLE_COUNT/2 && streams[i].next_is_upper_half) {
streams[i].next_is_upper_half = false;
if (can_refill) { // could we need a refill?
verbosef("Filling channel %d with upper half\n", i);
streamf("Filling channel %d with upper half\n", i);
// fill upper half
spu_memload(streams[i].aica_buffers[0] + STREAM_CHANNEL_BUFFER_SIZE/2, streams[i].buffer, STREAM_CHANNEL_BUFFER_SIZE/2);
if (streams[i].stereo) {
@@ -433,7 +458,7 @@ cSampleManager::Initialise(void)
// if end of file, stop
if ((streams[i].played_samples + logical_pos) > streams[i].total_samples) {
// stop channel
debugf("Auto stopping stream: %d -> {%d, %d}, %d total\n", i, streams[i].mapped_ch[0], streams[i].mapped_ch[1], streams[i].total_samples);
streamf("Auto stopping stream: %d -> {%d, %d}, %d total\n", i, streams[i].mapped_ch[0], streams[i].mapped_ch[1], streams[i].total_samples);
aica_stop_chn(streams[i].mapped_ch[0]);
aica_stop_chn(streams[i].mapped_ch[1]);
streams[i].playing = false;
@@ -441,7 +466,7 @@ cSampleManager::Initialise(void)
}
if (do_read) {
debugf("Queueing stream read: %d, file: %d, buffer: %p, size: %d, tell: %d\n", i, streams[i].fd, streams[i].buffer, do_read, fs_tell(streams[i].fd));
streamf("Queueing stream read: %d, file: %d, buffer: %p, size: %d, file_offset: %d\n", i, streams[i].fd, streams[i].buffer, do_read, streams[i].file_offset);
CdStreamQueueAudioRead(streams[i].fd, streams[i].buffer, do_read, streams[i].file_offset);
streams[i].file_offset += do_read;
}
@@ -481,6 +506,7 @@ cSampleManager::Initialise(void)
void
cSampleManager::Terminate(void)
{
CdStreamDiscardAudioRead(fdPedSfx);
fs_close(fdPedSfx);
}
@@ -519,6 +545,7 @@ void
cSampleManager::SetMusicMasterVolume(uint8 nVolume)
{
m_nMusicVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -532,6 +559,7 @@ void
cSampleManager::SetMusicFadeVolume(uint8 nVolume)
{
m_nMusicFadeVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -568,26 +596,29 @@ cSampleManager::LoadSampleBank(uint8 nBank)
// TODO: Split per-bank sfx file
int fd = fs_open(SampleBankDataFilename, O_RDONLY);
assert(fd >= 0);
// this is very wasteful and temporary
void* stagingBuffer = memalign(32, 32 * 2048);
assert(stagingBuffer != 0);
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
// Ideally, we'd suspend the CdStream thingy here or read via that instead
uintptr_t loadOffset = bank.base;
fs_seek(fd, fileStart, SEEK_SET);
// Ideally, we'd suspend the CdStream thingy here or read via that instead
uintptr_t loadOffset = bank.base;
fs_seek(fd, fileStart, SEEK_SET);
while (fileSize > 0) {
size_t readSize = fileSize > 32 * 2048 ? 32 * 2048 : fileSize;
int rs = fs_read(fd, stagingBuffer, readSize);
debugf("Read %d bytes, expected %d\n", rs, readSize);
assert(rs == readSize);
spu_memload(loadOffset, stagingBuffer, readSize);
loadOffset += readSize;
fileSize -= readSize;
debugf("Loaded %d bytes, %d remaining\n", readSize, fileSize);
while (fileSize > 0) {
size_t readSize = fileSize > sizeof(stagingBufferBank) ? sizeof(stagingBufferBank) : fileSize;
int rs = fs_read(fd, stagingBuffer, readSize);
debugf("Read %d bytes, expected %d\n", rs, readSize);
assert(rs == readSize);
spu_memload(loadOffset, stagingBuffer, readSize);
loadOffset += readSize;
fileSize -= readSize;
debugf("Loaded %d bytes, %d remaining\n", readSize, fileSize);
}
}
fs_close(fd);
free(stagingBuffer);
for (int nSfx = BankStartOffset[nBank]; nSfx < BankStartOffset[nBank+1]; nSfx++) {
@@ -728,23 +759,27 @@ cSampleManager::LoadPedComment(uint32 nComment)
assert(m_aSamples[nComment].nByteSize <= PED_BLOCKSIZE_ADPCM);
CdStreamQueueAudioRead(nComment, (void*)nPedSlotSfxAddr[nCurrentPedSlot], m_aSamples[nComment].nByteSize, m_aSamples[nComment].nFileOffset, [](AudioReadCmd* cmd) {
CdStreamQueueAudioRead(fdPedSfx, (void*)nPedSlotSfxAddr[nCurrentPedSlot], m_aSamples[nComment].nByteSize, m_aSamples[nComment].nFileOffset, [](AudioReadCmd* cmd) {
debugf("Loading ped comment %d, offset: %d, size: %d\n", nComment, m_aSamples[nComment].nFileOffset, m_aSamples[nComment].nByteSize);
fs_seek(fdPedSfx, cmd->seek, SEEK_SET);
assert(fs_seek(fdPedSfx, cmd->seek, SEEK_SET) == cmd->seek);
// TODO: When we can dma directly to AICA, we can use this instead
// fs_read(fdPedSfx, SPU_BASE_U8 + (uintptr_t)cmd->dest, cmd->size);
void* stagingBuffer = memalign(32, cmd->size);
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
free(stagingBuffer);
assert(cmd->size < sizeof(stagingBufferBank));
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
}
nPedSfxReqReadId = nPedSfxReqReadId + 1;
});
@@ -1014,7 +1049,7 @@ cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream, uint32_t seek_by
{
ASSERT( nStream < MAX_STREAMS );
file_t f = fs_open(DCStreamedNameTable[nFile], O_RDONLY);
debugf("PreloadStreamedFile(%p, %d, %d) is %s\n", f, nFile, nStream, DCStreamedNameTable[nFile]);
streamf("PreloadStreamedFile(%p, %d, %d) is %s\n", f, nFile, nStream, DCStreamedNameTable[nFile]);
assert(f >= 0 );
WavHeader hdr;
assert(fs_read(f, &hdr, sizeof(hdr)) == sizeof(hdr));
@@ -1037,13 +1072,13 @@ cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream, uint32_t seek_by
streams[nStream].next_is_upper_half = true;
streams[nStream].first_refill = true;
debugf("PreloadStreamedFile: %s: stream: %d, freq: %d, chans: %d, byte size: %d, played samples: %d\n", DCStreamedNameTable[nFile], nStream, hdr.samplesPerSec, hdr.numOfChan, hdr.dataSize, streams[nStream].played_samples);
streamf("PreloadStreamedFile: %s: stream: %d, freq: %d, chans: %d, byte size: %d, played samples: %d\n", DCStreamedNameTable[nFile], nStream, hdr.samplesPerSec, hdr.numOfChan, hdr.dataSize, streams[nStream].played_samples);
// How to avoid the lock?
if (seek_bytes_aligned) {
streams[nStream].played_samples = seek_bytes_aligned * (streams[nStream].stereo ? 1 : 2);
debugf("Seeking aligned to: %d, played_samples: %d\n", seek_bytes_aligned, streams[nStream].played_samples);
streamf("Seeking aligned to: %d, played_samples: %d\n", seek_bytes_aligned, streams[nStream].played_samples);
fs_seek(streams[nStream].fd, 2048 + seek_bytes_aligned, SEEK_SET);
} else {
fs_seek(f, 2048, SEEK_SET);
@@ -1072,7 +1107,7 @@ cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream, uint32_t seek_by
streams[nStream].file_offset = fs_tell(f);
}
verbosef("PreloadStreamedFile: %p %d - %s, %d, %d, \n", f, nFile, DCStreamedNameTable[nFile], streams[nStream].rate, streams[nStream].stereo);
streamf("PreloadStreamedFile: %p %d - %s, %d, %d, \n", f, nFile, DCStreamedNameTable[nFile], streams[nStream].rate, streams[nStream].stereo);
}
// we can't really pause a stream, so we just make it go very slow with zero volume
@@ -1195,12 +1230,29 @@ cSampleManager::GetStreamedFilePosition(uint8 nStream)
return rv;
}
static uint8 nStreamVolumes[MAX_STREAMS];
static uint8 nStreamPans[MAX_STREAMS];
static uint8 nStreamEffect[MAX_STREAMS];
void
cSampleManager::UpdateStreamsVolume(void)
{
if(_bSampmanInitialised) {
for (int nStream = 0; nStream < MAX_STREAMS; nStream++) {
SetStreamedVolumeAndPan(nStreamVolumes[nStream], nStreamPans[nStream], nStreamEffect[nStream], nStream);
}
}
}
void
cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream)
{
ASSERT( nStream < MAX_STREAMS );
if (nVolume > MAX_VOLUME)
nVolume = MAX_VOLUME;
nStreamVolumes[nStream] = nVolume;
nStreamPans[nStream] = nPan;
nStreamEffect[nStream] = nEffectFlag;
nVolume = linearlize_volume(nVolume); //nVolume * 255 / MAX_VOLUME;
nVolume = m_nMusicFadeVolume * nVolume * m_nMusicVolume >> 14;
if (streams[nStream].vol != nVolume || streams[nStream].nPan != nPan) {
@@ -1268,6 +1320,8 @@ cSampleManager::InitialiseSampleBanks(void)
assert(m_aSamples[nComment].nByteSize <= PED_BLOCKSIZE_ADPCM);
}
assert(PED_BLOCKSIZE_ADPCM <= BANK_STAGE_SIZE);
LoadSampleBank(SFX_BANK_0);
return TRUE;

View File

@@ -1,6 +1,6 @@
#pragma once
struct CColLine
struct alignas(8) CColLine
{
// NB: this has to be compatible with two CVuVectors
CVector p0;

View File

@@ -2,6 +2,9 @@
#include "ColModel.h"
#include "Game.h"
#include "MemoryHeap.h"
#include "Collision.h"
void* re3StreamingAlloc(size_t size);
CColModel::CColModel(void)
{
@@ -22,12 +25,12 @@ CColModel::CColModel(void)
CColModel::~CColModel(void)
{
RemoveCollisionVolumes();
RemoveTrianglePlanes();
}
void
CColModel::RemoveCollisionVolumes(void)
{
CCollision::RemoveTrianglePlanes(this);
if(ownsCollisionVolumes){
RwFree(spheres);
RwFree(lines);
@@ -93,6 +96,8 @@ CColModel::operator=(const CColModel &other)
int i;
int numVerts;
CCollision::RemoveTrianglePlanes(this);
boundingSphere = other.boundingSphere;
boundingBox = other.boundingBox;
@@ -163,7 +168,7 @@ CColModel::operator=(const CColModel &other)
if(vertices)
RwFree(vertices);
if(numVerts){
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
vertices = (CompressedVector*)re3StreamingAlloc(numVerts*sizeof(CompressedVector));
for(i = 0; i < numVerts; i++)
vertices[i] = other.vertices[i];
}
@@ -173,7 +178,7 @@ CColModel::operator=(const CColModel &other)
numTriangles = other.numTriangles;
if(triangles)
RwFree(triangles);
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
triangles = (CColTriangle*)re3StreamingAlloc(numTriangles*sizeof(CColTriangle));
}
for(i = 0; i < numTriangles; i++)
triangles[i] = other.triangles[i];

View File

@@ -1,6 +1,6 @@
#pragma once
struct CColPoint
struct alignas(8) CColPoint
{
CVector point;
int pad1;

View File

@@ -2,12 +2,17 @@
#include "SurfaceTable.h"
struct CColSphere
struct alignas(8) CColSphere
{
// NB: this has to be compatible with a CVuVector
CVector center;
float radius;
uint8 surface;
uint8 piece;
void Set(float radius, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0) {
this->radius = radius;
this->surface = surf;
this->piece = piece;
}
void Set(float radius, const CVector &center, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0);
};

View File

@@ -23,6 +23,10 @@
#include "Collision.h"
#include "Frontend.h"
#ifdef DC_SH4
#include "VuCollision.h"
#endif
#ifdef VU_COLLISION
#include "VuCollision.h"
@@ -737,7 +741,12 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
// transform line to model space
Invert(matrix, matTransform);
CColLine newline(matTransform * line.p0, matTransform * line.p1);
CColLine newline;
#ifndef DC_SH4
newline.Set(matTransform * line.p0, matTransform * line.p1);
#else
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
#endif
// If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(newline, model.boundingBox))
@@ -1577,7 +1586,12 @@ CCollision::ProcessLineOfSight(const CColLine &line,
// transform line to model space
Invert(matrix, matTransform);
CColLine newline(matTransform * line.p0, matTransform * line.p1);
CColLine newline;
#ifdef DC_SH4
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
#else
newline.Set(matTransform * line.p0, matTransform * line.p1);
#endif
// If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(newline, model.boundingBox))
@@ -1601,8 +1615,18 @@ CCollision::ProcessLineOfSight(const CColLine &line,
}
if(coldist < mindist){
#ifndef DC_SH4
point.point = matrix * point.point;
point.normal = Multiply3x3(matrix, point.normal);
#else
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrix)));
mat_trans_single3_nodiv(point.point.x,
point.point.y,
point.point.z);
mat_trans_normal3(point.normal.x,
point.normal.y,
point.normal.z);
#endif
mindist = coldist;
return true;
}
@@ -1739,9 +1763,14 @@ CCollision::ProcessVerticalLine(const CColLine &line,
// transform line to model space
// Why does the game seem to do this differently than above?
CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1));
newline.p1.x = newline.p0.x;
newline.p1.y = newline.p0.y;
CMatrix matTransform;
Invert(matrix, matTransform);
CColLine newline;
#ifndef DC_SH4
newline.Set(matTransform * line.p0, matTransform * line.p1);
#else
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
#endif
if(!TestVerticalLineBox(newline, model.boundingBox))
return false;
@@ -1765,14 +1794,31 @@ CCollision::ProcessVerticalLine(const CColLine &line,
}
if(coldist < mindist){
#ifndef DC_SH4
point.point = matrix * point.point;
point.normal = Multiply3x3(matrix, point.normal);
#else
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrix)));
mat_trans_single3_nodiv(point.point.x,
point.point.y,
point.point.z);
mat_trans_normal3(point.normal.x,
point.normal.y,
point.normal.z);
#endif
if(TempStoredPoly.valid && poly){
*poly = TempStoredPoly;
#ifndef DC_SH4
poly->verts[0] = matrix * poly->verts[0];
poly->verts[1] = matrix * poly->verts[1];
poly->verts[2] = matrix * poly->verts[2];
#else
mat_trans_single3_nodiv(poly->verts[0].x, poly->verts[0].y, poly->verts[0].z);
mat_trans_single3_nodiv(poly->verts[1].x, poly->verts[1].y, poly->verts[1].z);
mat_trans_single3_nodiv(poly->verts[2].x, poly->verts[2].y, poly->verts[2].z);
#endif
}
mindist = coldist;
return true;
}
@@ -2123,25 +2169,60 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
assert(modelA.numLines <= MAXNUMLINES);
// From model A space to model B space
matAB = Invert(matrixB, matAB);
Invert(matrixB, matAB);
#ifndef DC_SH4
matAB *= matrixA;
#else
mat_load(reinterpret_cast<const matrix_t*>(&matAB));
mat_apply(reinterpret_cast<const matrix_t*>(&matrixA));
#endif
CColSphere bsphereAB; // bounding sphere of A in B space
bsphereAB.radius = modelA.boundingSphere.radius;
#ifndef DC_SH4
bsphereAB.center = matAB * modelA.boundingSphere.center;
#else
mat_trans_single3_nodiv_nomod(modelA.boundingSphere.center.x,
modelA.boundingSphere.center.y,
modelA.boundingSphere.center.z,
bsphereAB.center.x,
bsphereAB.center.y,
bsphereAB.center.z);
#endif
if(!TestSphereBox(bsphereAB, modelB.boundingBox))
return 0;
// B to A space
matBA = Invert(matrixA, matBA);
matBA *= matrixB;
// transform modelA's spheres and lines to B space
for(i = 0; i < modelA.numSpheres; i++){
CColSphere &s = modelA.spheres[i];
#ifndef DC_SH4
aSpheresA[i].Set(s.radius, matAB * s.center, s.surface, s.piece);
#else
auto &d = aSpheresA[i];
mat_trans_single3_nodiv_nomod(s.center.x, s.center.y, s.center.z,
d.center.x, d.center.y, d.center.z);
d.Set(s.radius, s.surface, s.piece);
#endif
}
for(i = 0; i < modelA.numLines; i++)
for(i = 0; i < modelA.numLines; i++) {
#ifndef DC_SH4
aLinesA[i].Set(matAB * modelA.lines[i].p0, matAB * modelA.lines[i].p1);
#else
mat_trans_single3_nodiv_nomod(modelA.lines[i].p0.x,
modelA.lines[i].p0.y,
modelA.lines[i].p0.z,
aLinesA[i].p0.x,
aLinesA[i].p0.y,
aLinesA[i].p0.z);
mat_trans_single3_nodiv_nomod(modelA.lines[i].p1.x,
modelA.lines[i].p1.y,
modelA.lines[i].p1.z,
aLinesA[i].p1.x,
aLinesA[i].p1.y,
aLinesA[i].p1.z);
#endif
}
// Test them against model B's bounding volumes
int numSpheresA = 0;
@@ -2160,9 +2241,26 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
int numSpheresB = 0;
int numBoxesB = 0;
int numTrianglesB = 0;
// B to A space
Invert(matrixA, matBA);
#ifndef DC_SH4
matBA *= matrixB;
#else
mat_load(reinterpret_cast<const matrix_t*>(&matBA));
mat_apply(reinterpret_cast<const matrix_t*>(&matrixB));
#endif
for(i = 0; i < modelB.numSpheres; i++){
s.radius = modelB.spheres[i].radius;
#ifndef DC_SH4
s.center = matBA * modelB.spheres[i].center;
#else
mat_trans_single3_nodiv_nomod(modelB.spheres[i].center.x,
modelB.spheres[i].center.y,
modelB.spheres[i].center.z,
s.center.x,
s.center.y,
s.center.z);
#endif
if(TestSphereBox(s, modelA.boundingBox))
aSphereIndicesB[numSpheresB++] = i;
}
@@ -2209,9 +2307,22 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
if(hasCollided)
numCollisions++;
}
#ifdef DC_SH4
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrixB)));
#endif
for(i = 0; i < numCollisions; i++){
#ifndef DC_SH4
spherepoints[i].point = matrixB * spherepoints[i].point;
spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal);
#else
mat_trans_single3_nodiv(spherepoints[i].point.x,
spherepoints[i].point.y,
spherepoints[i].point.z);
mat_trans_normal3(spherepoints[i].normal.x,
spherepoints[i].normal.y,
spherepoints[i].normal.z);
#endif
}
// And the same thing for the lines in A
@@ -2242,8 +2353,17 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
for(i = 0; i < numLinesA; i++)
if(aCollided[i]){
j = aLineIndicesA[i];
#ifndef DC_SH4
linepoints[j].point = matrixB * linepoints[j].point;
linepoints[j].normal = Multiply3x3(matrixB, linepoints[j].normal);
#else
mat_trans_single3_nodiv(linepoints[j].point.x,
linepoints[j].point.y,
linepoints[j].point.z);
mat_trans_normal3(linepoints[j].normal.x,
linepoints[j].normal.y,
linepoints[j].normal.z);
#endif
}
return numCollisions; // sphere collisions
@@ -2287,6 +2407,15 @@ CCollision::DistToLine(const CVector *l0, const CVector *l1, const CVector *poin
return (*point - closest).Magnitude();
}
void
CCollision::RemoveTrianglePlanes(CColModel *model)
{
if(model->trianglePlanes){
ms_colModelCache.Remove(model->GetLinkPtr());
model->RemoveTrianglePlanes();
}
}
void
CCollision::CalculateTrianglePlanes(CColModel *model)
{

View File

@@ -41,6 +41,7 @@ public:
static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
static void RemoveTrianglePlanes(CColModel *model);
static void CalculateTrianglePlanes(CColModel *model);
// all these return true if there's a collision

View File

@@ -479,6 +479,7 @@ RemoveFirstInQueue(Queue *queue)
}
std::vector<AudioReadCmd> pendingAudioReads;
volatile int pendingAudioRead_fd = -1;
#if !defined(DC_SH4)
std::mutex pendingAudioReadsMutex;
#endif
@@ -487,8 +488,9 @@ void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek, st
AudioReadCmd cmd = { pBuffer, fd, bytes, seek};
if (!callback) {
cmd.callback = [](AudioReadCmd* cmd){
lseek(cmd->fd, cmd->seek, SEEK_SET);
read(cmd->fd, cmd->dest, cmd->size);
assert(pendingAudioRead_fd == cmd->fd);
assert(lseek(cmd->fd, cmd->seek, SEEK_SET) == cmd->seek);
assert(read(cmd->fd, cmd->dest, cmd->size) == cmd->size);
};
} else {
cmd.callback = callback;
@@ -500,7 +502,7 @@ void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek, st
auto mask = irq_disable();
#endif
for (auto it = pendingAudioReads.rbegin(); it != pendingAudioReads.rend(); ++it) {
if (it->fd == -1 || it->fd == fd) {
if (it->fd == -1) {
*it = cmd;
goto out;
}
@@ -532,6 +534,12 @@ void CdStreamDiscardAudioRead(int fd) {
#if defined(DC_SH4)
irq_restore(mask);
#endif
while (pendingAudioRead_fd == fd) {
#if defined(DC_SH4)
thd_pass();
#endif
}
}
AudioReadCmd CdStreamNextAudioRead() {
@@ -548,6 +556,8 @@ AudioReadCmd CdStreamNextAudioRead() {
break;
}
}
assert(pendingAudioRead_fd == -1);
pendingAudioRead_fd = cmd.fd;
#if defined(DC_SH4)
irq_restore(mask);
#endif
@@ -568,6 +578,7 @@ int read_loop(int fd, void* pBuffer, size_t bytes) {
auto cmd = CdStreamNextAudioRead();
while (cmd.fd != -1) {
cmd.callback(&cmd);
pendingAudioRead_fd = -1;
cmd = CdStreamNextAudioRead();
}
}
@@ -584,6 +595,7 @@ void *CdStreamThread(void *param)
auto cmd = CdStreamNextAudioRead();
while (cmd.fd != -1) {
cmd.callback(&cmd);
pendingAudioRead_fd = -1;
cmd = CdStreamNextAudioRead();
}

View File

@@ -28,6 +28,8 @@
#include <kos/dbglog.h>
void* re3StreamingAlloc(size_t size);
char CFileLoader::ms_line[256];
const char*
@@ -221,7 +223,7 @@ CFileLoader::LoadCollisionFile(const char *filename)
mi = CModelInfo::GetModelInfo(modelname, nil);
if(mi){
if(mi->GetColModel()){
if(mi->GetColModel() && mi->DoesOwnColModel()){
LoadCollisionModel(work_buff+24, *mi->GetColModel(), modelname);
}else{
CColModel *model = new CColModel;
@@ -255,6 +257,24 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.boundingBox.max.z = *(float*)(buf+36);
model.numSpheres = *(int16*)(buf+40);
buf += 44;
if (model.spheres) {
RwFree(model.spheres);
}
if (model.lines) {
RwFree(model.lines);
}
if (model.boxes) {
RwFree(model.boxes);
}
if (model.vertices) {
RwFree(model.vertices);
}
if (model.triangles) {
RwFree(model.triangles);
}
if (model.trianglePlanes) {
CCollision::RemoveTrianglePlanes(&model);
}
if(model.numSpheres > 0){
model.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere));
REGISTER_MEMPTR(&model.spheres);
@@ -292,7 +312,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
int32 numVertices = *(int16*)buf;
buf += 4;
if(numVertices > 0){
model.vertices = (CompressedVector*)RwMalloc(numVertices*sizeof(CompressedVector));
model.vertices = (CompressedVector*)re3StreamingAlloc(numVertices*sizeof(CompressedVector));
REGISTER_MEMPTR(&model.vertices);
for(i = 0; i < numVertices; i++){
model.vertices[i].SetFixed(*(int16*)buf, *(int16*)(buf+2), *(int16*)(buf+4));
@@ -304,7 +324,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.numTriangles = *(int16*)buf;
buf += 4;
if(model.numTriangles > 0){
model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));
model.triangles = (CColTriangle*)re3StreamingAlloc(model.numTriangles*sizeof(CColTriangle));
REGISTER_MEMPTR(&model.triangles);
for(i = 0; i < model.numTriangles; i++){
model.triangles[i].Set(model.vertices, *(uint16*)buf, *(uint16*)(buf+2), *(uint16*)(buf+4), buf[6], buf[7]);
@@ -672,118 +692,383 @@ char *DoubleSidedNames[] = {
"sbwy_tunl_cstm2",
"sbwy_tunl_cstm1",
"tenmnt6ad",
"LUIGICLUBout",
"redlightbuild03",
"dinerind",
"dinerind02",
"franksclb02",
"glassfx1",
"lswank_inside",
"luigiineerclub",
"swank_inside",
"train_rust",
"glassfx2",
"glassfx3",
"glassfx4",
"glassfx55",
"glassfx_composh",
"glassfxsub1",
"glassfxsub2",
""
};
char *TreeNames[] = {
"coast_treepatch",
"comparknewtrees",
"comtreepatchprk",
"condotree01",
"condotree1",
"indatree03",
"indtreepatch5",
"indtreepatch06f",
"new_carprktrees",
"new_carprktrees4",
"newcoasttrees1",
"newcoasttrees2",
"newcoasttrees3",
"newtreepatch_sub",
"newtrees1_sub",
"newunitrepatch",
"pinetree_narrow",
"pinetree_wide",
"treencom2",
"treepatch",
"treepatch01_sub",
"treepatch02_sub",
"treepatch2",
"treepatch2b",
"treepatch03",
"treepatch03_sub",
"treepatch04_sub",
"treepatch05_sub",
"treepatch06_sub",
"treepatch07_sub",
"treepatch08_sub",
"treepatch09_sub",
"treepatch10_sub",
"treepatch11_sub",
"treepatch12_sub",
"treepatch13_sub",
"treepatch14_sub",
"treepatch15_sub",
"treepatch16_sub",
"treepatch17_sub",
"treepatch18_sub",
"treepatch19_sub",
"treepatch20_sub",
"treepatch21_sub",
"treepatch22_sub",
"treepatch23_sub",
"treepatch24_sub",
"treepatch25_sub",
"treepatch26_sub",
"treepatch27_sub",
"treepatch28_sub",
"treepatch29_sub",
"treepatch30_sub",
"treepatch31_sub",
"treepatch32_sub",
"treepatch33_sub",
"treepatch34_sub",
"treepatch35_sub",
"treepatch69",
"treepatch152_sub",
"treepatch153_sub",
"treepatch171_sub",
"treepatch172_sub",
"treepatch173_sub",
"treepatch212_sub",
"treepatch213_sub",
"treepatch214_sub",
"treepatcha",
"treepatchb",
"treepatchcomtop1",
"treepatchd",
"treepatche",
"treepatchh",
"treepatchindaa2",
"treepatchindnew",
"treepatchindnew2",
"treepatchk",
"treepatchkb4",
"treepatchkb5",
"treepatchkb6",
"treepatchkb7",
"treepatchkb9",
"treepatchl",
"treepatchm",
"treepatchnew_sub",
"treepatchttwrs",
"treesuni1",
"trepatchindaa1",
"veg_bush2",
"veg_bush14",
"veg_tree1",
"veg_tree3",
"veg_treea1",
"veg_treea3",
"veg_treeb1",
"veg_treenew01",
"veg_treenew03",
"veg_treenew05",
"veg_treenew06",
"veg_treenew08",
"veg_treenew09",
"veg_treenew10",
"veg_treenew16",
"veg_treenew17",
"vegclubtree01",
"vegclubtree02",
"vegclubtree03",
"vegpathtree",
"Dam_pod1",
"building_fucked",
"ch_roof_kb",
"chtwn_fmrkt",
"hghwysgn01",
"hghwysgn02",
"hghwysgn_sub",
"ind_land037",
"ind_land125ind",
"indbilbridge1",
"industpatch05",
"iten_club01",
"iten_details7",
"iten_washline02",
"iten_washline03",
"mak_Watertank",
"mak_Watertank2",
"mak_Watertank3",
"pharmas",
"rd_Road1A5",
"rdsign02bk",
"rdsign06",
"rdsign14",
"rdsign15",
"rdsign17",
"rdsign18bk",
"rdsign19",
"rdsign19",
"wire_shed",
"Dam_pod2",
"Dineradam",
"Gdyn_barrier17",
"LODky_skyscrp6",
"LODt_skyscrp1",
"LODy_skyscrp23",
"LODy_skyscrp26b",
"Pumpfirescape",
"Pumphouse",
"airtower1",
"airtower2",
"bar_barrier10",
"bar_barrier10b",
"bar_barrier12",
"bar_barrier16",
"bar_barriergate1",
"barrierturn",
"billboard01",
"billboard02",
"billboard03",
"carlift01",
"carlift02",
"carparkfence",
"casino_garden",
"chinabanner1",
"chinabanner2",
"chinabanner3",
"chinabanner4",
"coast_treepatch",
"comparknewtrees",
"comtreepatchprk",
"condo_ivy",
"condotree01",
"condotree1",
"cons_buid02",
"cranebasea",
"cranebaseb",
"cranesmalltop",
"cranetopa",
"cranetopb",
"csky_skyscrp23",
"csky_skyscrp26b",
"damfence01",
"damfence02",
"damfence03",
"damfence04",
"damfence05",
"damfence06",
"damfence07",
"damfence08",
"damfencing",
"dinerind",
"dinerind02",
"dinersign",
"doc_crane_cab",
"doc_crane_leggs",
"doc_shedbig1",
"doc_shedbig12",
"doc_shedbig13",
"doc_shedbig2",
"doc_shedbig3",
"doc_shedbig31",
"doc_shedbig4",
"fencesmallb",
"firescapa1",
"firescapb1",
"foundation",
"glassfx1",
"glassfx2",
"glassfx3",
"glassfx4",
"glassfx55",
"glassfx_composh",
"glassfxsub1",
"glassfxsub2",
"helix_barrier",
"ind_customroad001",
"ind_customroad002",
"ind_customroad003",
"ind_customroad004",
"ind_customroad005",
"ind_customroad006",
"ind_customroad008",
"ind_customroad009",
"ind_customroad010",
"ind_customroad011",
"ind_customroad012",
"ind_customroad013",
"ind_customroad014",
"ind_customroad015",
"ind_customroad016",
"ind_customroad017",
"ind_customroad018",
"ind_customroad019",
"ind_customroad020",
"ind_customroad021",
"ind_customroad022",
"ind_customroad023",
"ind_customroad024",
"ind_customroad025",
"ind_customroad026",
"ind_customroad028",
"ind_customroad029",
"ind_customroad033",
"ind_customroad034",
"ind_customroad035",
"ind_customroad036",
"ind_customroad037",
"ind_customroad038",
"ind_customroad039",
"ind_customroad040",
"ind_customroad041",
"ind_customroad042",
"ind_customroad043",
"ind_customroad044",
"ind_customroad045",
"ind_customroad046",
"ind_customroad047",
"ind_customroad048",
"ind_customroad049",
"ind_customroad050",
"ind_customroad051",
"ind_customroad052",
"ind_customroad053",
"ind_customroad054",
"ind_customroad055",
"ind_customroad056",
"ind_customroad057",
"ind_customroad058",
"ind_customroad059",
"ind_customroad060",
"ind_customroad061",
"ind_customroad062",
"ind_customroad063",
"ind_customroad064",
"ind_customroad065",
"ind_customroad066",
"ind_customroad067",
"ind_customroad068",
"ind_customroad069",
"ind_customroad070",
"ind_customroad071",
"ind_customroad072",
"ind_customroad073",
"ind_customroad074",
"ind_customroad075",
"ind_customroad076",
"ind_customroad077",
"ind_customroad078",
"ind_customroad079",
"ind_customroad080",
"ind_customroad081",
"ind_customroad082",
"ind_customroad083",
"ind_customroad084",
"ind_customroad085",
"ind_customroad086",
"ind_customroad087",
"ind_customroad088",
"ind_customroad089",
"ind_customroad090",
"ind_customroad091",
"ind_customroad093",
"ind_customroad094",
"ind_customroad095",
"ind_customroad096",
"ind_customroad097",
"ind_customroad098",
"ind_customroad099",
"ind_customroad0bb",
"indatree03",
"indhelix_barrier",
"indjunk",
"indtreepatch06f",
"indtreepatch5",
"iten_washline01",
"kmricndo01",
"kmricndo02",
"lhouse_barrier1",
"lhouse_barrier2",
"lhouse_barrier3",
"mak_billboard",
"mak_billboardsrvc",
"mscp_barrier",
"mscp_barrier01",
"mscp_barriersup",
"nbbridgerda",
"nbbridgerdb",
"new_carprktrees",
"new_carprktrees4",
"newairportwall1",
"newairportwall2",
"newairportwall3",
"newairportwall4",
"newairportwall5",
"newairportwall6",
"newcoasttrees1",
"newcoasttrees2",
"newcoasttrees3",
"newtreepatch_sub",
"newtrees1_sub",
"newunitrepatch",
"nrailsteps",
"nrailstepswest",
"overpassind",
"pinetree_narrow",
"pinetree_wide",
"plnt_chimgrad",
"plnt_pipepart01",
"plnt_pipjoin4way04",
"plnt_pylon01",
"rd_Road1A10",
"salvsdetail",
"salvstrans",
"skyscrapenew",
"skyscrpunbuilt2",
"sub_billboard1",
"sub_tripbboard",
"subfraightback02",
"subfraightback03",
"subfraightback04",
"subsign1",
"tall_fence",
"tcsky_skyscrp6",
"telepole",
"telepole01",
"telepole02",
"telepole03",
"telepole04",
"tenkb_builds01",
"tenkb_builds03",
"tenkb_builds04",
"tenkb_builds05",
"tenkb_builds06",
"tenkb_builds11",
"trainstairst",
"treencom2",
"treepatch",
"treepatch01_sub",
"treepatch02_sub",
"treepatch03",
"treepatch03_sub",
"treepatch04_sub",
"treepatch05_sub",
"treepatch06_sub",
"treepatch07_sub",
"treepatch08_sub",
"treepatch09_sub",
"treepatch10_sub",
"treepatch11_sub",
"treepatch12_sub",
"treepatch13_sub",
"treepatch14_sub",
"treepatch152_sub",
"treepatch153_sub",
"treepatch15_sub",
"treepatch16_sub",
"treepatch171_sub",
"treepatch172_sub",
"treepatch173_sub",
"treepatch17_sub",
"treepatch18_sub",
"treepatch19_sub",
"treepatch2",
"treepatch20_sub",
"treepatch212_sub",
"treepatch213_sub",
"treepatch214_sub",
"treepatch21_sub",
"treepatch22_sub",
"treepatch23_sub",
"treepatch24_sub",
"treepatch25_sub",
"treepatch26_sub",
"treepatch27_sub",
"treepatch28_sub",
"treepatch29_sub",
"treepatch2b",
"treepatch30_sub",
"treepatch31_sub",
"treepatch32_sub",
"treepatch33_sub",
"treepatch34_sub",
"treepatch35_sub",
"treepatch69",
"treepatcha",
"treepatchb",
"treepatchcomtop1",
"treepatchd",
"treepatche",
"treepatchh",
"treepatchindaa2",
"treepatchindnew",
"treepatchindnew2",
"treepatchk",
"treepatchkb4",
"treepatchkb5",
"treepatchkb6",
"treepatchkb7",
"treepatchkb9",
"treepatchl",
"treepatchm",
"treepatchnew_sub",
"treepatchttwrs",
"treesuni1",
"trepatchindaa1",
"veg_bush14",
"veg_bush2",
"veg_tree1",
"veg_tree3",
"veg_treea1",
"veg_treea3",
"veg_treeb1",
"veg_treenew01",
"veg_treenew03",
"veg_treenew05",
"veg_treenew06",
"veg_treenew08",
"veg_treenew09",
"veg_treenew10",
"veg_treenew16",
"veg_treenew17",
"vegclubtree01",
"vegclubtree02",
"vegclubtree03",
"vegpathtree",
"wlst_skyscrp1",
""
};
char *OptimizedNames[] = {

View File

@@ -1170,6 +1170,24 @@ bool re3EmergencyRemoveModel() {
return usedmem != CStreaming::ms_memoryUsed;
}
void* re3StreamingAlloc(size_t size) {
auto rv = RwMalloc(size);
while (rv == nil) {
if (re3RemoveLeastUsedModel()) {
rv = RwMalloc(size);
continue;
}
if (re3EmergencyRemoveModel()) {
rv = RwMalloc(size);
continue;
}
return nil;
}
return rv;
}
bool
CStreaming::RemoveLeastUsedModel(void)
{

View File

@@ -94,6 +94,10 @@
#include <sys/stat.h>
#include <cctype>
#ifdef DC_SH4
#include <dc/vmu_pkg.h>
#endif
namespace mINI
{
namespace INIStringUtil
@@ -335,6 +339,7 @@ namespace mINI
private:
std::ifstream fileReadStream;
T_LineDataPtr lineData;
std::size_t start_offt;
T_LineData readFile()
{
@@ -343,7 +348,7 @@ namespace mINI
fileContents.resize(fileReadStream.tellg());
fileReadStream.seekg(0, std::ios::beg);
std::size_t fileSize = fileContents.size();
fileReadStream.read(&fileContents[0], fileSize);
fileReadStream.read(const_cast<char *>(fileContents.c_str()), fileSize);
fileReadStream.close();
T_LineData output;
if (fileSize == 0)
@@ -352,7 +357,19 @@ namespace mINI
}
std::string buffer;
buffer.reserve(50);
for (std::size_t i = 0; i < fileSize; ++i)
#ifdef DC_SH4
{
vmu_pkg_t vmu_pkg;
if(vmu_pkg_parse(reinterpret_cast<uint8*>(const_cast<int8*>(fileContents.c_str())), &vmu_pkg) != 0) {
// If we failed to parse, we assume it's raw with no VMS header.
start_offt = 0;
} else {
start_offt = reinterpret_cast<unsigned int>(vmu_pkg.data)
- reinterpret_cast<unsigned int>(fileContents.c_str());
}
}
#endif
for (std::size_t i = start_offt; i < fileSize; ++i)
{
char& c = fileContents[i];
if (c == '\n')
@@ -378,6 +395,8 @@ namespace mINI
{
lineData = std::make_shared<T_LineData>();
}
start_offt = 0;
}
~INIReader() { }
@@ -426,22 +445,71 @@ namespace mINI
{
private:
std::ofstream fileWriteStream;
std::stringstream memStream;
inline static std::ios_base::iostate lastError_;
public:
bool prettyPrint = false;
INIGenerator(std::string const& filename)
INIGenerator(std::string const& filename, bool prettyPrint_=false)
: fileWriteStream(filename, std::ios::out | std::ios::binary),
prettyPrint(prettyPrint_)
{
fileWriteStream.open(filename, std::ios::out | std::ios::binary);
lastError_ = fileWriteStream.rdstate();
}
~INIGenerator()
{
if(!fileWriteStream.good()) {
return;
}
std::string str = memStream.str();
const char *buf = str.c_str();
int buf_size = memStream.tellp();
#ifdef DC_SH4
uint8_t *data;
uint8_t icon_buf[512 * 1];
vmu_pkg_t vmu_pkg = {
.desc_short = "DCA-L Config",
.desc_long = "DCA-L Settings File",
.app_id = "The Gang",
.icon_cnt = 1,
.icon_anim_speed = 0,
.data_len = buf_size,
.icon_data = icon_buf,
.data = reinterpret_cast<const uint8_t*>(buf),
};
if (vmu_pkg_load_icon(&vmu_pkg, "settings.ico") < 0) {
vmu_pkg.icon_cnt = 0;
}
if(vmu_pkg_build(&vmu_pkg, &data, &buf_size) < 0) {
lastError_ = std::ios_base::badbit;
return;
}
buf = reinterpret_cast<char*>(data);
#endif
fileWriteStream.write(buf, buf_size);
lastError_ = fileWriteStream.rdstate();
#ifdef DC_SH4
// Must free the internal buffer allocated by vmu_pkg_build().
free(data);
#endif
}
bool operator<<(const std::string& str)
{
memStream << str;
return true;
}
~INIGenerator() { }
bool operator<<(INIStructure const& data)
{
if (!fileWriteStream.is_open())
{
return false;
}
if (!data.size())
{
return true;
@@ -451,13 +519,13 @@ namespace mINI
{
auto const& section = it->first;
auto const& collection = it->second;
fileWriteStream
memStream
<< "["
<< section
<< "]";
if (collection.size())
{
fileWriteStream << INIStringUtil::endl;
memStream << INIStringUtil::endl;
auto it2 = collection.begin();
for (;;)
{
@@ -465,7 +533,7 @@ namespace mINI
INIStringUtil::replace(key, "=", "\\=");
auto value = it2->second;
INIStringUtil::trim(value);
fileWriteStream
memStream
<< key
<< ((prettyPrint) ? " = " : "=")
<< value;
@@ -473,21 +541,29 @@ namespace mINI
{
break;
}
fileWriteStream << INIStringUtil::endl;
memStream << INIStringUtil::endl;
}
}
if (++it == data.end())
{
break;
}
fileWriteStream << INIStringUtil::endl;
memStream << INIStringUtil::endl;
if (prettyPrint)
{
fileWriteStream << INIStringUtil::endl;
memStream << INIStringUtil::endl;
}
}
return true;
}
operator bool() const
{
return fileWriteStream.rdstate() == fileWriteStream.goodbit;
}
static std::ios_base::iostate lastError() { return lastError_; }
static bool wasGood() { return lastError_ == std::ios_base::goodbit; }
};
class INIWriter
@@ -667,12 +743,15 @@ namespace mINI
{
struct stat buf;
bool fileExists = (stat(filename.c_str(), &buf) == 0);
if (!fileExists)
{
INIGenerator generator(filename);
generator.prettyPrint = prettyPrint;
return generator << data;
if(INIGenerator generator(filename, prettyPrint); generator) {
generator << data;
}
return INIGenerator::wasGood();
}
INIStructure originalData;
T_LineDataPtr lineData;
bool readSuccess = false;
@@ -688,23 +767,21 @@ namespace mINI
return false;
}
T_LineData output = getLazyOutput(lineData, data, originalData);
std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
if (fileWriteStream.is_open())
{
if (output.size())
if (INIGenerator generator(filename, prettyPrint); generator && output.size())
{
auto line = output.begin();
for (;;)
{
fileWriteStream << *line;
generator << *line;
if (++line == output.end())
{
break;
}
fileWriteStream << INIStringUtil::endl;
generator << INIStringUtil::endl;
}
}
return true;
return INIGenerator::wasGood();
}
return false;
}
@@ -741,9 +818,10 @@ namespace mINI
{
return false;
}
INIGenerator generator(filename);
generator.prettyPrint = pretty;
return generator << data;
if(INIGenerator generator(filename, pretty); generator) {
generator << data;
}
return INIGenerator::wasGood();
}
bool write(INIStructure& data, bool pretty = false) const
{

View File

@@ -1,11 +1,5 @@
#include "common.h"
CMatrix::CMatrix(void)
{
m_attachment = nil;
m_hasRwMatrix = false;
}
CMatrix::CMatrix(CMatrix const &m)
{
m_attachment = nil;
@@ -510,14 +504,9 @@ operator*(const CMatrix &m1, const CMatrix &m2)
{
// TODO: VU0 code
CMatrix out;
#if defined(RW_DC) && 0 // THIS IS BROKEN, 4th element shouldn't be processed
# ifdef DC_SH4
MATH_Load_Matrix_Product(reinterpret_cast<const matrix_t *>(&m1), reinterpret_cast<const matrix_t *>(&m2));
# elif defined(RW_DC)
mat_load(reinterpret_cast<const matrix_t *>(&m2));
mat_apply(reinterpret_cast<const matrix_t *>(&m1));
# endif
#if defined(RW_DC)
mat_load(reinterpret_cast<const matrix_t *>(&m1));
mat_apply(reinterpret_cast<const matrix_t *>(&m2));
mat_store(reinterpret_cast<matrix_t *>(&out));
#else
out.rx = m1.rx * m2.rx + m1.fx * m2.ry + m1.ux * m2.rz;

View File

@@ -1,6 +1,6 @@
#pragma once
class CMatrix
class alignas(8) CMatrix
{
public:
union
@@ -8,17 +8,17 @@ public:
alignas(8) float f[4][4];
struct alignas(8)
{
float rx, ry, rz, rw;
float fx, fy, fz, fw;
float ux, uy, uz, uw;
float px, py, pz, pw;
float rx, ry, rz, rw=0.0f;
float fx, fy, fz, fw=0.0f;
float ux, uy, uz, uw=0.0f;
float px, py, pz, pw=1.0f;
};
};
RwMatrix *m_attachment;
bool m_hasRwMatrix; // are we the owner?
RwMatrix *m_attachment = nil;
bool m_hasRwMatrix = false; // are we the owner?
CMatrix(void);
CMatrix(void) {}
CMatrix(CMatrix const &m);
CMatrix(RwMatrix *matrix, bool owner = false);
CMatrix(float scale){

View File

@@ -45,7 +45,7 @@ __always_inline void TransformPoint(CVuVector &out, const CMatrix &mat, const CV
": : "r" (&out) , "r" (&mat) ,"r" (&in): "memory");
#elif defined(DC_SH4)
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&mat)));
mat_trans_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z, out.y);
mat_trans_single3_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z);
#else
out = mat * in;
#endif
@@ -72,7 +72,7 @@ __always_inline void TransformPoint(CVuVector &out, const CMatrix &mat, const Rw
": : "r" (&out) , "r" (&mat) ,"r" (&in): "memory");
#elif defined(DC_SH4)
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&mat)));
mat_trans_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z, out.y);
mat_trans_single3_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z);
#else
out = mat * in;
#endif
@@ -80,7 +80,6 @@ __always_inline void TransformPoint(CVuVector &out, const CMatrix &mat, const Rw
__always_inline void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride)
{
assert(false);
#ifdef GTA_PS2
__asm__ __volatile__("\n\
paddub $3,%4,$0\n\
@@ -110,9 +109,11 @@ __always_inline void TransformPoints(CVuVector *out, int n, const CMatrix &mat,
": : "r" (out) , "r" (n), "r" (&mat), "r" (in), "r" (stride): "memory");
#elif defined(DC_SH4)
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&mat)));
mat_transform(reinterpret_cast<vector_t *>(const_cast<RwV3d *>(in)),
reinterpret_cast<vector_t *>(out),
n, stride - sizeof(vector_t));
while(n--) {
mat_trans_single3_nodiv_nomod(in->x, in->y, in->z, out->x, out->y, out->z);
in = reinterpret_cast<const RwV3d *>(reinterpret_cast<const uint8_t *>(in) + stride);
++out;
}
#else
while(n--){
*out = mat * *in;

View File

@@ -38,6 +38,14 @@ CBaseModelInfo::DeleteCollisionModel(void)
}
}
void CBaseModelInfo::SetColModel(CColModel *col, bool owns) {
if (m_bOwnsColModel) {
delete m_colModel;
}
m_colModel = col;
m_bOwnsColModel = owns;
}
void
CBaseModelInfo::AddRef(void)
{

View File

@@ -56,8 +56,7 @@ public:
}
char *GetModelName(void) { return m_name; }
void SetModelName(const char *name) { strncpy(m_name, name, MAX_MODEL_NAME); }
void SetColModel(CColModel *col, bool owns = false){
m_colModel = col; m_bOwnsColModel = owns; }
void SetColModel(CColModel *col, bool owns = false);
CColModel *GetColModel(void) { return m_colModel; }
bool DoesOwnColModel(void) { return m_bOwnsColModel; }
void DeleteCollisionModel(void);

View File

@@ -197,6 +197,10 @@ CCutsceneHead::PlayAnimation(const char *animName)
RwStreamSkip(stream, offset*2048);
if(RwStreamFindChunk(stream, rwID_HANIMANIMATION, nil, nil)){
anim = RpHAnimAnimationStreamRead(stream);
if (hier->interpolator->currentAnim) {
RpHAnimAnimationDestroy(hier->interpolator->currentAnim);
hier->interpolator->currentAnim = nil;
}
RpHAnimHierarchySetCurrentAnim(hier, anim);
}

View File

@@ -39,7 +39,11 @@
#define AMMO_X 66.0f
#define HEALTH_X 110.0f
#define STARS_X 60.0f
#ifdef RW_DC
#define ZONE_Y 64.0f
#else
#define ZONE_Y 30.0f
#endif
#define VEHICLE_Y 55.0f
#define CLOCK_X 111.0f
#define SUBS_Y 68.0f

View File

@@ -58,7 +58,11 @@ public:
};
enum {
#ifdef RW_DC
NUM_RAIN_STREAKS = 10
#elif
NUM_RAIN_STREAKS = 35
#endif
};
struct tRainStreak

View File

@@ -17,6 +17,8 @@
#include "vmu/vmu.h"
void* re3StreamingAlloc(size_t size);
const char* _psGetUserFilesFolder();
C_PcSave PcSaveHelper;
@@ -93,16 +95,17 @@ uint32_t C_PcSave::PcClassLoadRoutine(int32 file, uint8 *data) {
return size;
} else {
size &= ~0x80000000;
uint8* compressed = (uint8*)malloc(size);
uint8* compressed = (uint8*)re3StreamingAlloc(size);
assert(compressed);
err = CFileMgr::Read(file, (const char*)compressed, size) != size;
if (err || CFileMgr::GetErrorReadWrite(file)) {
free(compressed);
RwFree(compressed);
return 0;
}
lzo_uint decompressed_size = 0;
auto crv = lzo1x_decompress(compressed, size, data, &decompressed_size, NULL);
free(compressed);
RwFree(compressed);
if (crv != LZO_E_OK) {
return 0;
}
@@ -117,31 +120,37 @@ uint32_t C_PcSave::PcClassLoadRoutine(int32 file, uint8 *data) {
bool
C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
{
void* wrkmem = malloc(LZO1X_1_MEM_COMPRESS);
uint8* compressed = (uint8*)malloc(size*2);
void* wrkmem = re3StreamingAlloc(LZO1X_1_MEM_COMPRESS);
assert(wrkmem);
uint8* compressed = (uint8*)re3StreamingAlloc(size*2);
assert(compressed);
lzo_uint compressed_size;
int crv = lzo1x_1_compress(data, size, compressed, &compressed_size, wrkmem);
free(wrkmem);
RwFree(wrkmem);
if (crv == LZO_E_OK && compressed_size >= size) {
crv = LZO_E_NOT_COMPRESSIBLE;
}
if (crv == LZO_E_OK) {
uint32_t compressed_size32 = compressed_size | 0x80000000;
bool err = CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)) != sizeof(compressed_size32);
if (err || CFileMgr::GetErrorReadWrite(file)) {
free(compressed);
RwFree(compressed);
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false;
}
err = CFileMgr::Write(file, (const char*)compressed, compressed_size) != compressed_size;
free(compressed);
RwFree(compressed);
if (err || CFileMgr::GetErrorReadWrite(file)) {
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false;
}
} else if (crv == LZO_E_NOT_COMPRESSIBLE) {
free(compressed);
RwFree(compressed);
uint32_t compressed_size32 = size;
bool err = CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)) != sizeof(compressed_size32);
if (err || CFileMgr::GetErrorReadWrite(file)) {
@@ -156,7 +165,7 @@ C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
return false;
}
} else {
free(compressed);
RwFree(compressed);
return false;
}

View File

@@ -12,6 +12,8 @@
#include "AnimManager.h"
#include "Streaming.h"
void* re3StreamingAlloc(size_t size);
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
int32 CAnimManager::ms_numAnimBlocks;
@@ -1312,7 +1314,7 @@ CAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*uncompressedA
uint16_t flags;
RwStreamRead(stream, &flags, sizeof(flags));
seq->keyFrames = RwMalloc(dataSize);
seq->keyFrames = re3StreamingAlloc(dataSize);
assert(seq->keyFrames);
RwStreamRead(stream, seq->keyFrames, dataSize - sizeof(flags));
seq->type = flags;

View File

@@ -419,7 +419,8 @@ CCutsceneMgr::DeleteCutsceneData(void)
CBaseModelInfo *minfo = CModelInfo::GetModelInfo(i);
CColModel *colModel = minfo->GetColModel();
if (colModel != &CTempColModels::ms_colModelPed1) {
delete colModel;
// no need to delete anymore, SetColModel will do it (~skmp)
//delete colModel;
minfo->SetColModel(&CTempColModels::ms_colModelPed1);
}
}

View File

@@ -5220,6 +5220,10 @@ cAudioManager::ProcessPedOneShots(cPedParams &params)
if (iSound > 60)
iSound = 21;
}
// In some cases the left and right channels have different loop points
// This looks like a data file issue where the left and right channels have different loop points
// This is a hot fix to always have the correct loop point for each channel individually
SET_LOOP_OFFSETS(m_sQueueSample.m_nSampleIndex)
AddSampleToRequestedQueue();
}
}

View File

@@ -198,6 +198,7 @@ public:
char GetCDAudioDriveLetter (void);
void UpdateEffectsVolume(void);
void UpdateStreamsVolume(void);
#ifdef DC_SH4
void UpdateChannelVolume(uint32 nChannel);

View File

@@ -12,6 +12,8 @@
#include "thread/thread.h"
#if !defined(AUDIO_OAL) && !defined(AUDIO_MSS)
#define syncf(...) // dbglog(DBG_CRITICAL, __VA_ARGS__)
#define streamf(...) // dbglog(DBG_CRITICAL, __VA_ARGS__)
#define verbosef(...) // dbglog(DBG_CRITICAL, __VA_ARGS__)
#define debugf(...) // dbglog(DBG_CRITICAL, __VA_ARGS__)
@@ -46,6 +48,8 @@
/* Quick access to the AICA channels */
#define AICA_CHANNEL(x) (AICA_MEM_CHANNELS + (x) * sizeof(aica_channel_t))
static uint32_t chn_version[64];
int aica_play_chn(int chn, int size, uint32_t aica_buffer, int fmt, int vol, int pan, int loop, int freq) {
// assert(size <= 65534);
// We gotta fix this at some point
@@ -69,6 +73,7 @@ int aica_play_chn(int chn, int size, uint32_t aica_buffer, int fmt, int vol, int
chan->freq = freq;
chan->vol = vol;
chan->pan = pan;
chan->version = ++chn_version[chn];
snd_sh4_to_aica(tmp, cmd->size);
return chn;
}
@@ -182,6 +187,12 @@ uintptr_t gPlayerTalkData = 0;
uint32 gPlayerTalkReqId = 0;
#endif
// this is very wasteful and temporary
#define BANK_STAGE_SIZE 16 * 2048
static uint8_t stagingBufferBank[BANK_STAGE_SIZE] __attribute__((aligned(32)));
std::mutex stagingBufferMtx;
static int32 DCStreamedLength[TOTAL_STREAMED_SOUNDS];
struct WavHeader {
@@ -364,6 +375,12 @@ cSampleManager::Initialise(void)
if (channels[i].ch != -1) {
assert(channels[i].nSfx != -1);
uint32_t channel_version = g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(channels[i].ch) + offsetof(aica_channel_t, version));
if (chn_version[channels[i].ch] != channel_version) {
syncf("SFX version missmatch, skipping update. expected %d got %d\n", chn_version[channels[i].ch], channel_version);
continue;
}
uint16_t channel_pos = (g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(channels[i].ch) + offsetof(aica_channel_t, pos)) & 0xffff);
// verbosef("Channel %d pos: %d\n", i, channel_pos);
if (!channels[i].loop) {
@@ -390,21 +407,27 @@ cSampleManager::Initialise(void)
{
std::lock_guard<std::mutex> lk(streams[i].mtx);
if (streams[i].playing) {
uint32_t channel_version = g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(streams[i].mapped_ch[0]) + offsetof(aica_channel_t, version));
if (chn_version[streams[i].mapped_ch[0]] != channel_version) {
syncf("Stream version missmatch, skipping update. expected %d got %d\n", chn_version[streams[i].mapped_ch[0]], channel_version);
continue;
}
// get channel pos
uint32_t channel_pos = g2_read_32(SPU_RAM_UNCACHED_BASE + AICA_CHANNEL(streams[i].mapped_ch[0]) + offsetof(aica_channel_t, pos)) & 0xffff;
uint32_t logical_pos = channel_pos;
if (logical_pos > STREAM_CHANNEL_SAMPLE_COUNT/2) {
logical_pos -= STREAM_CHANNEL_SAMPLE_COUNT/2;
}
verbosef("Stream %d pos: %d, log: %d, rem: %d\n", i, channel_pos, logical_pos, streams[i].played_samples);
streamf("Stream %d pos: %d, log: %d, played: %d\n", i, channel_pos, logical_pos, streams[i].played_samples);
bool can_refill = (streams[i].played_samples + STREAM_CHANNEL_SAMPLE_COUNT/2) < streams[i].total_samples;
bool can_fetch = (streams[i].played_samples + STREAM_CHANNEL_SAMPLE_COUNT/2 + STREAM_CHANNEL_SAMPLE_COUNT/2 + STREAM_CHANNEL_SAMPLE_COUNT/2) < streams[i].total_samples;
bool can_refill = (streams[i].played_samples + STREAM_CHANNEL_SAMPLE_COUNT/2 + (!streams[i].first_refill)*STREAM_CHANNEL_SAMPLE_COUNT/2) < streams[i].total_samples;
bool can_fetch = (streams[i].played_samples + STREAM_CHANNEL_SAMPLE_COUNT/2 + STREAM_CHANNEL_SAMPLE_COUNT/2 + (!streams[i].first_refill)*STREAM_CHANNEL_SAMPLE_COUNT/2) < streams[i].total_samples;
// copy over data if needed from staging
if (channel_pos >= STREAM_CHANNEL_SAMPLE_COUNT/2 && !streams[i].next_is_upper_half) {
streams[i].next_is_upper_half = true;
if (can_refill) { // could we need a refill?
verbosef("Filling channel %d with lower half\n", i);
streamf("Filling channel %d with lower half\n", i);
// fill lower half
spu_memload(streams[i].aica_buffers[0], streams[i].buffer, STREAM_CHANNEL_BUFFER_SIZE/2);
if (streams[i].stereo) {
@@ -420,7 +443,7 @@ cSampleManager::Initialise(void)
} else if (channel_pos < STREAM_CHANNEL_SAMPLE_COUNT/2 && streams[i].next_is_upper_half) {
streams[i].next_is_upper_half = false;
if (can_refill) { // could we need a refill?
verbosef("Filling channel %d with upper half\n", i);
streamf("Filling channel %d with upper half\n", i);
// fill upper half
spu_memload(streams[i].aica_buffers[0] + STREAM_CHANNEL_BUFFER_SIZE/2, streams[i].buffer, STREAM_CHANNEL_BUFFER_SIZE/2);
if (streams[i].stereo) {
@@ -440,7 +463,7 @@ cSampleManager::Initialise(void)
// if end of file, stop
if ((streams[i].played_samples + logical_pos) > streams[i].total_samples) {
// stop channel
debugf("Auto stopping stream: %d -> {%d, %d}, %d total\n", i, streams[i].mapped_ch[0], streams[i].mapped_ch[1], streams[i].total_samples);
streamf("Auto stopping stream: %d -> {%d, %d}, %d total\n", i, streams[i].mapped_ch[0], streams[i].mapped_ch[1], streams[i].total_samples);
aica_stop_chn(streams[i].mapped_ch[0]);
aica_stop_chn(streams[i].mapped_ch[1]);
streams[i].playing = false;
@@ -448,7 +471,7 @@ cSampleManager::Initialise(void)
}
if (do_read) {
debugf("Queueing stream read: %d, file: %d, buffer: %p, size: %d, tell: %d\n", i, streams[i].fd, streams[i].buffer, do_read, fs_tell(streams[i].fd));
streamf("Queueing stream read: %d, file: %d, buffer: %p, size: %d, file_offset: %d\n", i, streams[i].fd, streams[i].buffer, do_read, streams[i].file_offset);
CdStreamQueueAudioRead(streams[i].fd, streams[i].buffer, do_read, streams[i].file_offset);
streams[i].file_offset += do_read;
}
@@ -488,6 +511,7 @@ cSampleManager::Initialise(void)
void
cSampleManager::Terminate(void)
{
CdStreamDiscardAudioRead(fdPedSfx);
fs_close(fdPedSfx);
}
@@ -514,7 +538,6 @@ cSampleManager::UpdateEffectsVolume(void)
}
}
void
cSampleManager::SetEffectsMasterVolume(uint8 nVolume)
{
@@ -526,6 +549,7 @@ void
cSampleManager::SetMusicMasterVolume(uint8 nVolume)
{
m_nMusicVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -545,6 +569,7 @@ void
cSampleManager::SetMusicFadeVolume(uint8 nVolume)
{
m_nMusicFadeVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -581,26 +606,29 @@ cSampleManager::LoadSampleBank(uint8 nBank)
// TODO: Split per-bank sfx file
int fd = fs_open(SampleBankDataFilename, O_RDONLY);
assert(fd >= 0);
// this is very wasteful and temporary
void* stagingBuffer = memalign(32, 8 * 2048);
assert(stagingBuffer != 0);
// Ideally, we'd suspend the CdStream thingy here or read via that instead
uintptr_t loadOffset = bank.base;
fs_seek(fd, fileStart, SEEK_SET);
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
assert(stagingBuffer != 0);
while (fileSize > 0) {
size_t readSize = fileSize > 8 * 2048 ? 8 * 2048 : fileSize;
int rs = fs_read(fd, stagingBuffer, readSize);
debugf("Read %d bytes, expected %d\n", rs, readSize);
assert(rs == readSize);
spu_memload(loadOffset, stagingBuffer, readSize);
loadOffset += readSize;
fileSize -= readSize;
debugf("Loaded %d bytes, %d remaining\n", readSize, fileSize);
// Ideally, we'd suspend the CdStream thingy here or read via that instead
uintptr_t loadOffset = bank.base;
while (fileSize > 0) {
size_t readSize = fileSize > sizeof(stagingBufferBank) ? sizeof(stagingBufferBank) : fileSize;
int rs = fs_read(fd, stagingBuffer, readSize);
debugf("Read %d bytes, expected %d\n", rs, readSize);
assert(rs == readSize);
spu_memload(loadOffset, stagingBuffer, readSize);
loadOffset += readSize;
fileSize -= readSize;
debugf("Loaded %d bytes, %d remaining\n", readSize, fileSize);
}
}
fs_close(fd);
free(stagingBuffer);
for (int nSfx = BankStartOffset[nBank]; nSfx < BankStartOffset[nBank+1]; nSfx++) {
@@ -687,21 +715,25 @@ cSampleManager::LoadMissionAudio(uint8 nSlot, uint32 nSample)
ASSERT(nSample < TOTAL_AUDIO_SAMPLES);
debugf("Loading mission audio comment %d, offset: %d, size: %d\n", nSample, m_aSamples[nSample].nFileOffset, m_aSamples[nSample].nByteSize);
CdStreamQueueAudioRead(nSample, (void*)gPlayerTalkData, m_aSamples[nSample].nByteSize, m_aSamples[nSample].nFileOffset, [](AudioReadCmd* cmd) {
fs_seek(fdPedSfx, cmd->seek, SEEK_SET);
CdStreamQueueAudioRead(fdPedSfx, (void*)gPlayerTalkData, m_aSamples[nSample].nByteSize, m_aSamples[nSample].nFileOffset, [](AudioReadCmd* cmd) {
assert(fs_seek(fdPedSfx, cmd->seek, SEEK_SET) == cmd->seek);
// TODO: When we can dma directly to AICA, we can use this instead
// fs_read(fdPedSfx, SPU_BASE_U8 + (uintptr_t)cmd->dest, cmd->size);
void* stagingBuffer = memalign(32, cmd->size);
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
free(stagingBuffer);
assert(cmd->size < sizeof(stagingBufferBank));
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
}
nPedSfxReqReadId = nPedSfxReqReadId + 1;
});
@@ -780,22 +812,26 @@ cSampleManager::LoadPedComment(uint32 nComment)
assert(m_aSamples[nComment].nByteSize <= pedBlocksizeMax);
debugf("Loading ped comment %d, offset: %d, size: %d\n", nComment, m_aSamples[nComment].nFileOffset, m_aSamples[nComment].nByteSize);
CdStreamQueueAudioRead(nComment, (void*)nPedSlotSfxAddr[nCurrentPedSlot], m_aSamples[nComment].nByteSize, m_aSamples[nComment].nFileOffset, [](AudioReadCmd* cmd) {
fs_seek(fdPedSfx, cmd->seek, SEEK_SET);
CdStreamQueueAudioRead(fdPedSfx, (void*)nPedSlotSfxAddr[nCurrentPedSlot], m_aSamples[nComment].nByteSize, m_aSamples[nComment].nFileOffset, [](AudioReadCmd* cmd) {
assert(fs_seek(fdPedSfx, cmd->seek, SEEK_SET) == cmd->seek);
// TODO: When we can dma directly to AICA, we can use this instead
// fs_read(fdPedSfx, SPU_BASE_U8 + (uintptr_t)cmd->dest, cmd->size);
void* stagingBuffer = memalign(32, cmd->size);
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
assert(cmd->size < sizeof(stagingBufferBank));
{
std::lock_guard lk(stagingBufferMtx); // for stagingBufferBank
void* stagingBuffer = stagingBufferBank;
assert(stagingBuffer != 0);
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
assert(rs == cmd->size);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
}
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
free(stagingBuffer);
nPedSfxReqReadId = nPedSfxReqReadId + 1;
});
@@ -1081,7 +1117,7 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream, uint32_t seek_b
ASSERT( nFile < TOTAL_STREAMED_SOUNDS );
file_t f = fs_open(DCStreamedNameTable[nFile], O_RDONLY);
debugf("PreloadStreamedFile(%p, %d, %d) is %s\n", f, nFile, nStream, DCStreamedNameTable[nFile]);
streamf("PreloadStreamedFile(%p, %d, %d) is %s\n", f, nFile, nStream, DCStreamedNameTable[nFile]);
assert(f >= 0 );
WavHeader hdr;
assert(fs_read(f, &hdr, sizeof(hdr)) == sizeof(hdr));
@@ -1113,13 +1149,13 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream, uint32_t seek_b
streams[nStream].next_is_upper_half = true;
streams[nStream].first_refill = true;
debugf("PreloadStreamedFile: %s: stream: %d, freq: %d, chans: %d, byte size: %d, played samples: %d\n", DCStreamedNameTable[nFile], nStream, hdr.samplesPerSec, hdr.numOfChan, hdr.dataSize, streams[nStream].played_samples);
streamf("PreloadStreamedFile: %s: stream: %d, freq: %d, chans: %d, byte size: %d, played samples: %d\n", DCStreamedNameTable[nFile], nStream, hdr.samplesPerSec, hdr.numOfChan, hdr.dataSize, streams[nStream].played_samples);
// How to avoid the lock?
if (seek_bytes_aligned) {
streams[nStream].played_samples = seek_bytes_aligned * (streams[nStream].stereo ? 1 : 2);
debugf("Seeking aligned to: %d, played_samples: %d\n", seek_bytes_aligned, streams[nStream].played_samples);
streamf("Seeking aligned to: %d, played_samples: %d\n", seek_bytes_aligned, streams[nStream].played_samples);
fs_seek(streams[nStream].fd, 2048 + seek_bytes_aligned, SEEK_SET);
} else {
fs_seek(f, 2048, SEEK_SET);
@@ -1148,7 +1184,7 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream, uint32_t seek_b
streams[nStream].file_offset = fs_tell(f);
}
verbosef("PreloadStreamedFile: %p %d - %s, %d, %d, \n", f, nFile, DCStreamedNameTable[nFile], streams[nStream].rate, streams[nStream].stereo);
streamf("PreloadStreamedFile: %p %d - %s, %d, %d, \n", f, nFile, DCStreamedNameTable[nFile], streams[nStream].rate, streams[nStream].stereo);
}
// we can't really pause a stream, so we just make it go very slow with zero volume
@@ -1275,12 +1311,28 @@ cSampleManager::GetStreamedFilePosition(uint8 nStream)
return rv;
}
static uint8 nStreamVolumes[MAX_STREAMS];
static uint8 nStreamPans[MAX_STREAMS];
static uint8 nStreamEffect[MAX_STREAMS];
void
cSampleManager::UpdateStreamsVolume(void)
{
if(_bSampmanInitialised) {
for (int nStream = 0; nStream < MAX_STREAMS; nStream++) {
SetStreamedVolumeAndPan(nStreamVolumes[nStream], nStreamPans[nStream], nStreamEffect[nStream], nStream);
}
}
}
void
cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream)
{
ASSERT( nStream < MAX_STREAMS );
if (nVolume > MAX_VOLUME)
nVolume = MAX_VOLUME;
nStreamVolumes[nStream] = nVolume;
nStreamPans[nStream] = nPan;
nStreamEffect[nStream] = nEffectFlag;
nVolume = linearlize_volume(nVolume); //nVolume * 255 / MAX_VOLUME;
nVolume = m_nMusicFadeVolume * nVolume * m_nMusicVolume >> 14;
if (streams[nStream].vol != nVolume || streams[nStream].nPan != nPan) {
@@ -1349,16 +1401,21 @@ cSampleManager::InitialiseSampleBanks(void)
for (uint32 nComment = SAMPLEBANK_PED_START; nComment <= SAMPLEBANK_PED_END; nComment++) {
pedBlocksizeMax = Max(pedBlocksizeMax, m_aSamples[nComment].nByteSize);
}
assert(pedBlocksizeMax <= BANK_STAGE_SIZE);
debugf("Max ped comment size: %d\n", pedBlocksizeMax);
#ifdef FIX_BUGS
// Find biggest player comment
uint32 nMaxPlayerSize = 0;
for (uint32 i = PLAYER_COMMENTS_START; i <= PLAYER_COMMENTS_END; i++)
for (uint32 i = PLAYER_COMMENTS_START; i <= PLAYER_COMMENTS_END; i++) {
nMaxPlayerSize = Max(nMaxPlayerSize, m_aSamples[i].nByteSize);
}
debugf("Max player comment size: %d\n", nMaxPlayerSize);
assert(nMaxPlayerSize < sizeof(stagingBufferBank));
gPlayerTalkData = snd_mem_malloc(nMaxPlayerSize);
ASSERT(gPlayerTalkData != 0);

View File

@@ -1,6 +1,6 @@
#pragma once
struct CColLine
struct alignas(8) CColLine
{
// NB: this has to be compatible with two CVuVectors
CVector p0;

View File

@@ -5,6 +5,8 @@
#include "MemoryHeap.h"
#include "Pools.h"
void* re3StreamingAlloc(size_t size);
CColModel::CColModel(void)
{
numSpheres = 0;
@@ -43,13 +45,13 @@ CColModel::operator delete(void *p, size_t) throw()
void
CColModel::RemoveCollisionVolumes(void)
{
CCollision::RemoveTrianglePlanes(this);
if(ownsCollisionVolumes){
RwFree(spheres);
RwFree(lines);
RwFree(boxes);
RwFree(vertices);
RwFree(triangles);
CCollision::RemoveTrianglePlanes(this);
}
numSpheres = 0;
numLines = 0;
@@ -109,6 +111,8 @@ CColModel::operator=(const CColModel &other)
int i;
int numVerts;
CCollision::RemoveTrianglePlanes(this);
boundingSphere = other.boundingSphere;
boundingBox = other.boundingBox;
@@ -179,7 +183,7 @@ CColModel::operator=(const CColModel &other)
if(vertices)
RwFree(vertices);
if(numVerts){
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
vertices = (CompressedVector*)re3StreamingAlloc(numVerts*sizeof(CompressedVector));
for(i = 0; i < numVerts; i++)
vertices[i] = other.vertices[i];
}
@@ -189,7 +193,7 @@ CColModel::operator=(const CColModel &other)
numTriangles = other.numTriangles;
if(triangles)
RwFree(triangles);
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
triangles = (CColTriangle*)re3StreamingAlloc(numTriangles*sizeof(CColTriangle));
}
for(i = 0; i < numTriangles; i++)
triangles[i] = other.triangles[i];

View File

@@ -1,6 +1,6 @@
#pragma once
struct CColPoint
struct alignas(8) CColPoint
{
CVector point;
int pad1;

View File

@@ -2,7 +2,7 @@
#include "SurfaceTable.h"
struct CSphere
struct alignas(8) CSphere
{
// NB: this has to be compatible with a CVuVector
CVector center;
@@ -15,6 +15,11 @@ struct CColSphere : public CSphere
uint8 surface;
uint8 piece;
void Set(float radius, uint8 surf = SURFACE_DEFAULT, uint8 piece = 0) {
this->radius = radius;
this->surface = surf;
this->piece = piece;
}
void Set(float radius, const CVector &center, uint8 surf, uint8 piece);
bool IntersectRay(CVector const &from, CVector const &dir, CVector &entry, CVector &exit);
using CSphere::Set;

View File

@@ -24,6 +24,10 @@
#include "Camera.h"
#include "ColStore.h"
#ifdef DC_SH4
#include "VuCollision.h"
#endif
#ifdef VU_COLLISION
#include "VuCollision.h"
@@ -572,7 +576,12 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
// transform line to model space
Invert(matrix, matTransform);
CColLine newline(matTransform * line.p0, matTransform * line.p1);
CColLine newline;
#ifndef DC_SH4
newline.Set(matTransform * line.p0, matTransform * line.p1);
#else
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
#endif
// If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(newline, model.boundingBox))
@@ -1428,7 +1437,12 @@ CCollision::ProcessLineOfSight(const CColLine &line,
// transform line to model space
Invert(matrix, matTransform);
CColLine newline(matTransform * line.p0, matTransform * line.p1);
CColLine newline;
#ifdef DC_SH4
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
#else
newline.Set(matTransform * line.p0, matTransform * line.p1);
#endif
// If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(newline, model.boundingBox))
@@ -1455,8 +1469,18 @@ CCollision::ProcessLineOfSight(const CColLine &line,
}
if(coldist < mindist){
#ifndef DC_SH4
point.point = matrix * point.point;
point.normal = Multiply3x3(matrix, point.normal);
#else
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrix)));
mat_trans_single3_nodiv(point.point.x,
point.point.y,
point.point.z);
mat_trans_normal3(point.normal.x,
point.normal.y,
point.normal.z);
#endif
mindist = coldist;
return true;
}
@@ -1593,7 +1617,14 @@ CCollision::ProcessVerticalLine(const CColLine &line,
// transform line to model space
// Why does the game seem to do this differently than above?
CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1));
CMatrix matTransform;
Invert(matrix, matTransform);
CColLine newline;
#ifndef DC_SH4
newline.Set(matTransform * line.p0, matTransform * line.p1);
#else
TransformPoints(reinterpret_cast<CVuVector*>(&newline), 2, matTransform, &line.p0, sizeof(CColLine)/2);
#endif
if(!TestLineBox(newline, model.boundingBox))
return false;
@@ -1618,13 +1649,29 @@ CCollision::ProcessVerticalLine(const CColLine &line,
}
if(coldist < mindist){
#ifndef DC_SH4
point.point = matrix * point.point;
point.normal = Multiply3x3(matrix, point.normal);
#else
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrix)));
mat_trans_single3_nodiv(point.point.x,
point.point.y,
point.point.z);
mat_trans_normal3(point.normal.x,
point.normal.y,
point.normal.z);
#endif
if(TempStoredPoly.valid && poly){
*poly = TempStoredPoly;
#ifndef DC_SH4
poly->verts[0] = matrix * poly->verts[0];
poly->verts[1] = matrix * poly->verts[1];
poly->verts[2] = matrix * poly->verts[2];
#else
mat_trans_single3_nodiv(poly->verts[0].x, poly->verts[0].y, poly->verts[0].z);
mat_trans_single3_nodiv(poly->verts[1].x, poly->verts[1].y, poly->verts[1].z);
mat_trans_single3_nodiv(poly->verts[2].x, poly->verts[2].y, poly->verts[2].z);
#endif
}
mindist = coldist;
return true;
@@ -1976,26 +2023,60 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
assert(modelA.numLines <= MAXNUMLINES);
// From model A space to model B space
matAB = Invert(matrixB, matAB);
Invert(matrixB, matAB);
#ifndef DC_SH4
matAB *= matrixA;
#else
mat_load(reinterpret_cast<const matrix_t*>(&matAB));
mat_apply(reinterpret_cast<const matrix_t*>(&matrixA));
#endif
CColSphere bsphereAB; // bounding sphere of A in B space
bsphereAB.radius = modelA.boundingSphere.radius;
#ifndef DC_SH4
bsphereAB.center = matAB * modelA.boundingSphere.center;
#else
mat_trans_single3_nodiv_nomod(modelA.boundingSphere.center.x,
modelA.boundingSphere.center.y,
modelA.boundingSphere.center.z,
bsphereAB.center.x,
bsphereAB.center.y,
bsphereAB.center.z);
#endif
if(!TestSphereBox(bsphereAB, modelB.boundingBox))
return 0;
// B to A space
matBA = Invert(matrixA, matBA);
matBA *= matrixB;
// transform modelA's spheres and lines to B space
for(i = 0; i < modelA.numSpheres; i++){
CColSphere &s = modelA.spheres[i];
#ifndef DC_SH4
aSpheresA[i].Set(s.radius, matAB * s.center, s.surface, s.piece);
#else
auto &d = aSpheresA[i];
mat_trans_single3_nodiv_nomod(s.center.x, s.center.y, s.center.z,
d.center.x, d.center.y, d.center.z);
d.Set(s.radius, s.surface, s.piece);
#endif
}
for(i = 0; i < modelA.numLines; i++)
aLinesA[i].Set(matAB * modelA.lines[i].p0, matAB * modelA.lines[i].p1);
for(i = 0; i < modelA.numLines; i++) {
#ifndef DC_SH4
aLinesA[i].Set(matAB * modelA.lines[i].p0, matAB * modelA.lines[i].p1);
#else
mat_trans_single3_nodiv_nomod(modelA.lines[i].p0.x,
modelA.lines[i].p0.y,
modelA.lines[i].p0.z,
aLinesA[i].p0.x,
aLinesA[i].p0.y,
aLinesA[i].p0.z);
mat_trans_single3_nodiv_nomod(modelA.lines[i].p1.x,
modelA.lines[i].p1.y,
modelA.lines[i].p1.z,
aLinesA[i].p1.x,
aLinesA[i].p1.y,
aLinesA[i].p1.z);
#endif
}
// Test them against model B's bounding volumes
int numSpheresA = 0;
int numLinesA = 0;
@@ -2013,9 +2094,26 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
int numSpheresB = 0;
int numBoxesB = 0;
int numTrianglesB = 0;
// B to A space
Invert(matrixA, matBA);
#ifndef DC_SH4
matBA *= matrixB;
#else
mat_load(reinterpret_cast<const matrix_t*>(&matBA));
mat_apply(reinterpret_cast<const matrix_t*>(&matrixB));
#endif
for(i = 0; i < modelB.numSpheres; i++){
s.radius = modelB.spheres[i].radius;
#ifndef DC_SH4
s.center = matBA * modelB.spheres[i].center;
#else
mat_trans_single3_nodiv_nomod(modelB.spheres[i].center.x,
modelB.spheres[i].center.y,
modelB.spheres[i].center.z,
s.center.x,
s.center.y,
s.center.z);
#endif
if(TestSphereBox(s, modelA.boundingBox))
aSphereIndicesB[numSpheresB++] = i;
}
@@ -2062,9 +2160,22 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
if(hasCollided)
numCollisions++;
}
#ifdef DC_SH4
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&matrixB)));
#endif
for(i = 0; i < numCollisions; i++){
#ifndef DC_SH4
spherepoints[i].point = matrixB * spherepoints[i].point;
spherepoints[i].normal = Multiply3x3(matrixB, spherepoints[i].normal);
#else
mat_trans_single3_nodiv(spherepoints[i].point.x,
spherepoints[i].point.y,
spherepoints[i].point.z);
mat_trans_normal3(spherepoints[i].normal.x,
spherepoints[i].normal.y,
spherepoints[i].normal.z);
#endif
}
// And the same thing for the lines in A
@@ -2095,8 +2206,17 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
for(i = 0; i < numLinesA; i++)
if(aCollided[i]){
j = aLineIndicesA[i];
#ifndef DC_SH4
linepoints[j].point = matrixB * linepoints[j].point;
linepoints[j].normal = Multiply3x3(matrixB, linepoints[j].normal);
#else
mat_trans_single3_nodiv(linepoints[j].point.x,
linepoints[j].point.y,
linepoints[j].point.z);
mat_trans_normal3(linepoints[j].normal.x,
linepoints[j].normal.y,
linepoints[j].normal.z);
#endif
}
return numCollisions; // sphere collisions

View File

@@ -479,6 +479,7 @@ RemoveFirstInQueue(Queue *queue)
}
std::vector<AudioReadCmd> pendingAudioReads;
volatile int pendingAudioRead_fd = -1;
#if !defined(DC_SH4)
std::mutex pendingAudioReadsMutex;
#endif
@@ -487,8 +488,9 @@ void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek, st
AudioReadCmd cmd = { pBuffer, fd, bytes, seek};
if (!callback) {
cmd.callback = [](AudioReadCmd* cmd){
lseek(cmd->fd, cmd->seek, SEEK_SET);
read(cmd->fd, cmd->dest, cmd->size);
assert(pendingAudioRead_fd == cmd->fd);
assert(lseek(cmd->fd, cmd->seek, SEEK_SET) == cmd->seek);
assert(read(cmd->fd, cmd->dest, cmd->size) == cmd->size);
};
} else {
cmd.callback = callback;
@@ -500,7 +502,7 @@ void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek, st
auto mask = irq_disable();
#endif
for (auto it = pendingAudioReads.rbegin(); it != pendingAudioReads.rend(); ++it) {
if (it->fd == -1 || it->fd == fd) {
if (it->fd == -1) {
*it = cmd;
goto out;
}
@@ -532,6 +534,12 @@ void CdStreamDiscardAudioRead(int fd) {
#if defined(DC_SH4)
irq_restore(mask);
#endif
while (pendingAudioRead_fd == fd) {
#if defined(DC_SH4)
thd_pass();
#endif
}
}
AudioReadCmd CdStreamNextAudioRead() {
@@ -548,6 +556,8 @@ AudioReadCmd CdStreamNextAudioRead() {
break;
}
}
assert(pendingAudioRead_fd == -1);
pendingAudioRead_fd = cmd.fd;
#if defined(DC_SH4)
irq_restore(mask);
#endif
@@ -568,6 +578,7 @@ int read_loop(int fd, void* pBuffer, size_t bytes) {
auto cmd = CdStreamNextAudioRead();
while (cmd.fd != -1) {
cmd.callback(&cmd);
pendingAudioRead_fd = -1;
cmd = CdStreamNextAudioRead();
}
}
@@ -584,6 +595,7 @@ void *CdStreamThread(void *param)
auto cmd = CdStreamNextAudioRead();
while (cmd.fd != -1) {
cmd.callback(&cmd);
pendingAudioRead_fd = -1;
cmd = CdStreamNextAudioRead();
}

View File

@@ -30,6 +30,8 @@
#include "ColStore.h"
#include "Occlusion.h"
void* re3StreamingAlloc(size_t size);
char CFileLoader::ms_line[256];
const char*
@@ -303,6 +305,24 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.boundingBox.max.z = *(float*)(buf+36);
model.numSpheres = *(int16*)(buf+40);
buf += 44;
if (model.spheres) {
RwFree(model.spheres);
}
if (model.lines) {
RwFree(model.lines);
}
if (model.boxes) {
RwFree(model.boxes);
}
if (model.vertices) {
RwFree(model.vertices);
}
if (model.triangles) {
RwFree(model.triangles);
}
if (model.trianglePlanes) {
CCollision::RemoveTrianglePlanes(&model);
}
if(model.numSpheres > 0){
model.spheres = (CColSphere*)RwMalloc(model.numSpheres*sizeof(CColSphere));
REGISTER_MEMPTR(&model.spheres);
@@ -360,7 +380,7 @@ CFileLoader::LoadCollisionModel(uint8 *buf, CColModel &model, char *modelname)
model.numTriangles = *(int16*)buf;
buf += 4;
if(model.numTriangles > 0){
model.triangles = (CColTriangle*)RwMalloc(model.numTriangles*sizeof(CColTriangle));
model.triangles = (CColTriangle*)re3StreamingAlloc(model.numTriangles*sizeof(CColTriangle));
REGISTER_MEMPTR(&model.triangles);
for(i = 0; i < model.numTriangles; i++){
model.triangles[i].Set(*(uint16*)buf, *(uint16*)(buf+2), *(uint16*)(buf+4), buf[6]);
@@ -698,269 +718,671 @@ CFileLoader::LoadObjectTypes(const char *filename)
//find . -type f -name "*rail*.dff" ! -name "*shad*"
//find . -type f -name "*veg*.dff" ! -name "*shad*"
char *AlphaTestNames[] = {
"xpolytrees2_dt",
"gf_treesfw3_01",
"ci_trees05",
"xpolytrees3_dt",
"LODrtrees5",
"LODrtrees2",
"nbt_mansiontrees04",
"malltreereflect2",
"veg_treeb1",
"LODrtrees4",
"Streetlamp2",
"nbt_mansiontrees02",
"LODmrgtrees4",
"gf_tree2_02",
"malltreereflect",
"nbt_hoteltrees02",
"veg_treea1",
"Streetlamp1",
"gf_treesfw5_01",
"nbt_mansiontrees05",
"malltrees01",
"xpolytrees4_dt",
"nbt_mansiontrees03",
"xpolytrees1_dt",
"hoteltrees01",
"hoteltrees03",
"gf_treesfw1_01",
"veg_tree3",
"ap_treeshot1_02",
"hoteltrees02",
"ci_trees03",
"veg_treea3",
"mc_treesfw3_01",
"ap_treesfw1_01",
"nbt_hoteltrees01",
"ci_trees04",
"gf_treesfw2_01",
"LODrtrees3",
"ci_trees1",
"mc_treesfw1_01",
"LODrtrees1",
"gf_treesfw4_01",
"nbt_mansiontrees01",
"hoteltrees06",
"mn_treesis_int",
"hoteltrees05",
"mc_treesfw2_01",
"gf_tree1_01",
"mn_treesisl05",
"doublestreetlght1",
"ci_trees02",
"bank_palms09",
"veg_palmkb3",
"lw_palm1",
"veg_palmkb5",
"bank_palms21",
"veg_palmkb1",
"veg_palmbig14",
"veg_palmkb14",
"veg_palm02",
"veg_palmkb2",
"veg_palmkb9",
"bank_palms28",
"veg_palmkb7",
"bank_palms23",
"bank_palms32",
"veg_palmkb8",
"bank_palms02",
"bank_palms33",
"veg_palmkbb11",
"veg_palmkb4",
"veg_palm01",
"veg_palm03",
"veg_palmkb13",
"veg_palmkb10",
"veg_palm04",
"gf_tennisfence",
"marinafence04",
"marinafence01",
"b_hse_pierfence",
"ap_wallfence5",
"dockfence",
"dtn_hospital_fence",
"mc_fence1",
"od_clubfence_dy",
"ap_wallfence1",
"const_woodfence30",
"bb_fence1",
"ap_seafences",
"marinafence03",
"nbthotel08fence02",
"dt_sheraton_fence",
"dt_scabby_fence04",
"nbt_barfence01",
"ap_wallfence2",
"od_clevelfence",
"mc_fence2",
"ci_fence2",
"dt_scabby_fence03",
"mansionfence",
"nbt_hotel07fence",
"marinafence02",
"fence01",
"compound_fence",
"ap_wallfence7",
"fencehaitism",
"od_clubfence_nt",
"marinafence05",
"ap_wallfence6",
"Mansion2_C_fence",
"dt_scabby_fence07",
"kickfence",
"pw_backfence1",
"mc_fence3",
"washfence1",
"LODst_woodfence30",
"washfence2",
"carparkfence0",
"ap_wallfence3",
"fencesmallb",
"ap_wallfence4",
"fencehaiti",
"stationfence",
"dt_scabby_fence01",
"pw_bayfence2_01",
"lha_carfence",
"tall_fence",
"ap_seaplanfence1",
"LODse_pierfence",
"marinaveg3",
"ml_vegbits05",
"svegrgedoor",
"ml_vegbits04",
"nrth3veg35",
"nrth3veg05",
"ht_veg01_nt",
"nbeachvegy1",
"odnvegbush1",
"washvegy4",
"ht_veg02_nt",
"wshotelveg1",
"dtn_veg3",
"nrth7veg09",
"washvegy238",
"veg_palwee02",
"nrth3veg50",
"washpshoutveg",
"nrth4veg08",
"washvegy3",
"washvegy241",
"washvegy2",
"washvegy239",
"odnvegbush2b",
"veg_gaz",
"nrth1veg21",
"ht_veg04_dy",
"ml_vegbits03",
"nbeachvegy2",
"nrth3veg16",
"ht_veg02_dy",
"nrth4veg05",
"ht_veg04_nt",
"veg_palwee01",
"ht_veg01_dy",
"vegeha1",
"veged",
"veg_ivy_balcny_kb3",
"nrth1veg42",
"marinaveg1",
"nrth3veg25",
"veg_fern_balcny_kb1",
"spad_veg1",
"washvegy2413",
"marinaveg2",
"washvegy240",
"vegetationb",
"nrth1veg37",
"ml_vegbits01",
"veged01",
"dtn_veg4",
"washvegy242",
"veg_palwee03",
"nrth3veg59",
"nrth4veg212",
"nrth4veg21",
"nrth7veg",
"washvegy237",
"nrth3veg08",
"nrth4veg09",
"veg_fern_balcny_kb2",
"ml_vegbits02",
"odnvegbush2",
"vegetationb03",
"veged02",
"kb_planterbox",
"plants05b",
"nbdecoshplants",
"ap_planters2_01",
"ml_planterbed",
"marinaplanter1",
"washskyplant1",
"dzplant",
"ci_planter2",
"ap_planters1_01",
"gf_planters4",
"washskyplant2",
"kb_planter+bush",
"marinaplanter2",
"ci_planter1",
"plants04",
"gf_planters2",
"kb_planterbush2",
"plants01",
"kb_planter+bush2",
"plants05",
"ci_busht_04",
"starsbush2",
"mansbushes2",
"odnvegbush1",
"odrv_bushes",
"ci_busht_02",
"mlmallbush",
"mansbushes",
"nbw_bush02",
"ci_busht_08",
"nbw_bush01",
"odnvegbush2b",
"ap_carbush2_01",
"new_bushtest42",
"new_bushsm",
"mallbushs",
"odrv_bushes01",
"kb_planter+bush",
"ci_busht_06",
"beach_bush08s",
"beach_bush06s",
"new_bushtest",
"doontoon66_bushes01",
"beach_bush04",
"starbitbush",
"beach_bush02",
"lhavnew_bush",
"kb_planterbush2",
"ci_busht_11",
"odnvegbush2",
"kb_planter+bush2",
"mallbushdense",
"dk_rail06",
"cl_railing",
"docks10rail",
"cl_railingb",
"dk_rail05",
"shpfrnts03rail01",
"dk_rail02",
"nbeachbit03rails",
"ci_mans1rail",
"dk_rail07",
"dk_rail01",
"ci_mans2rail1",
"ci_mans1rail1",
"dk_rail04",
"shpfrnts03rail02",
"dk_rail03",
"BillBd04",
"BillBd1",
"BillBd2",
"BillBd3",
"LODk_grassarea",
"LODmrgtrees4",
"LODo_polgrnda10",
"LODo_polgrnda12",
"LODo_polgrnda13",
"LODo_polgrnda14",
"LODo_polgrnda16",
"LODo_polgrnda17",
"LODo_polgrnda7",
"LODo_polgrnda8",
"LODo_polgrnda9",
"LODrtrees1",
"LODrtrees2",
"LODrtrees3",
"LODrtrees4",
"LODrtrees5",
"LODse_pierfence",
"LODst_woodfence30",
"Man3_base_hedge",
"Mansion2_C_fence",
"Rose_Bush01",
"Rose_Bush03",
"Starhouse",
"Streetlamp1",
"Streetlamp2",
"ap_blastdef_01",
"ap_blastdef_03",
"ap_boardshad1",
"ap_carbush2_01",
"ap_planters1_01",
"ap_planters2_01",
"ap_radar1_01",
"ap_seafences",
"ap_seaplanfence1",
"ap_stairsout02",
"ap_stairsout03",
"ap_stairsout04",
"ap_stairsout1",
"ap_subfraightback01",
"ap_subfraightback02",
"ap_subfraightback04",
"ap_treesfw1_01",
"ap_treeshot1_02",
"ap_wallfence1",
"ap_wallfence2",
"ap_wallfence3",
"ap_wallfence4",
"ap_wallfence5",
"ap_wallfence6",
"ap_wallfence7",
"b_hse_pierfence",
"bank_palms02",
"bank_palms09",
"bank_palms21",
"bank_palms23",
"bank_palms28",
"bank_palms32",
"bank_palms33",
"basketballcourt04",
"basketballcourt05",
"bb_fence1",
"beach_bush02",
"beach_bush04",
"beach_bush06s",
"beach_bush08s",
"biggrass2",
"bldigste1mesh",
"boatcranelg0",
"build1",
"buldingsite1",
"carparkfence0",
"chandelier",
"ci_astagelights",
"ci_astudganwal",
"ci_boards1",
"ci_boards2",
"ci_busht_02",
"ci_busht_04",
"ci_busht_06",
"ci_busht_08",
"ci_busht_11",
"ci_dstudiogantry",
"ci_fence2",
"ci_mans1rail",
"ci_mans1rail1",
"ci_mans2rail1",
"ci_planter1",
"ci_planter2",
"ci_pornsetxtra",
"ci_shipset",
"ci_stairsout01",
"ci_trees02",
"ci_trees03",
"ci_trees04",
"ci_trees05",
"ci_trees1",
"cl_curtains",
"cl_lightsuprts",
"cl_railing",
"cl_railingb",
"cl_recessedlights1",
"club_exterior01",
"club_exterior02",
"club_exterior06",
"club_exterior07",
"club_exterior08",
"club_exterior09",
"compound_fence",
"concerth.col",
"concerth02",
"concerth03",
"concerth04",
"concerth05",
"concerth06",
"concerth07",
"concerth08",
"concerth09",
"concerth10",
"concerth11",
"concerth12",
"concerth27",
"concerth29",
"concerth48",
"concerth49",
"concerth50",
"concerth51",
"concerth52",
"concerth54",
"concerth56",
"const_woodfence30",
"cranebasea0",
"crgoshp010",
"crocneon",
"deco_polgrnda10",
"deco_polgrnda12",
"deco_polgrnda13",
"deco_polgrnda14",
"deco_polgrnda16",
"deco_polgrnda17",
"deco_polgrnda7",
"deco_polgrnda8",
"deco_polgrnda9",
"dk_cargoshp01",
"dk_cargoshp03",
"dk_cargoshp04",
"dk_cargoshp05",
"dk_cargoshp10",
"dk_cargoshp100",
"dk_cargoshp12",
"dk_cargoshp24",
"dk_cargoshp25",
"dk_cargoshp28",
"dk_cargoshp31",
"dk_cargoshp32",
"dk_cargoshp35",
"dk_cargoshp40",
"dk_cargoshp41",
"dk_cargoshp47",
"dk_cargoshp50",
"dk_cargoshp51",
"dk_cargoshp53",
"dk_cargoshp54",
"dk_cargoshp64",
"dk_cargoshp65",
"dk_cargoshp66",
"dk_cargoshp68",
"dk_cargoshp70",
"dk_cargoshp71",
"dk_cargoshp72",
"dk_cargoshp73",
"dk_cargoshp76",
"dk_cargoshp95",
"dk_rail01",
"dk_rail02",
"dk_rail03",
"dk_rail03",
"dk_rail04",
"dk_rail05",
"dk_rail06",
"dk_rail07",
"doc_crane_cab0",
"doc_crane_cab01",
"doc_crane_cab02",
"doc_crane_cab03",
"doc_crane_cab04",
"doc_craneeggs04",
"dock_grassarea",
"dock_props01",
"dock_props02",
"dockcranescale0",
"dockcranescale01",
"dockfence",
"dockgate01",
"dockgate02",
"dockgrass",
"docks10",
"docks10rail",
"docksware01",
"doontoon18",
"doontoon25_alfas",
"doontoon32_alfa",
"doontoon66_bushes01",
"doontoon76",
"doublestreetlght1",
"drive_flowers06",
"dt_compound_alfas",
"dt_scabby_fence01",
"dt_scabby_fence03",
"dt_scabby_fence04",
"dt_scabby_fence07",
"dt_sheraton_fence",
"dt_stadium__alfa1",
"dtn_cablesa",
"dtn_cablesb",
"dtn_cablesc",
"dtn_cablesd",
"dtn_cablese",
"dtn_cablesf",
"dtn_hospital_fence",
"dtn_veg3",
"dtn_veg4",
"dts_telwire1",
"dts_telwire2",
"dts_telwire4",
"dts_telwire9",
"dzplant",
"fence01",
"fencehaiti",
"fencehaitism",
"fencesmallb",
"gf_drdivide1_01",
"gf_drivingrange1",
"gf_golfwall",
"gf_picket1_01",
"gf_planters2",
"gf_planters4",
"gf_stadlight1_02",
"gf_tennisfence",
"gf_tree1_01",
"gf_tree2_02",
"gf_treesfw1_01",
"gf_treesfw2_01",
"gf_treesfw3_01",
"gf_treesfw4_01",
"gf_treesfw5_01",
"grassbitsjm",
"grasspatch",
"haitinwire11",
"haitinwire22",
"haitinwire23",
"havanahouse12b",
"hoteltrees01",
"hoteltrees02",
"hoteltrees03",
"hoteltrees05",
"hoteltrees06",
"ht_veg01_dy",
"ht_veg01_nt",
"ht_veg02_dy",
"ht_veg02_nt",
"ht_veg04_dy",
"ht_veg04_nt",
"kb_planter",
"kb_planter+bush",
"kb_planter+bush2",
"kb_planterbox",
"kb_planterbush2",
"kickfence",
"labiggrass",
"labiggrass01",
"labiggrass02",
"lh_haiblockc3",
"lha_carfence",
"lhavnew_bush",
"lhbasket",
"lhbillboard05xx",
"lhroofst01",
"lhroofst02",
"lhroofst03",
"lhroofst04",
"lhroofst07",
"lhroofst08",
"lhroofst09",
"lhroofst10",
"lhroofst11",
"lhroofst12",
"lhroofst14",
"lhroofst16",
"lhroofst17",
"lhroofst18",
"lhroofst19",
"lhroofstuffg",
"lhsteps3",
"lithavabit01",
"lithavabit03",
"lithavabit04",
"lithavabit05",
"lithavabit06",
"lithavabit07",
"lithavabit08",
"lithavabit09",
"lithavabit10",
"lithavabit11",
"lithavabit12",
"littlehacoast02",
"littlehacoast05",
"lw_palm1",
"mallbushdense",
"mallbushs",
"malltreereflect",
"malltreereflect2",
"malltrees01",
"man_build01",
"man_build01_al",
"man_build02",
"man_build02_al",
"man_build03",
"man_build03_al",
"man_build04",
"man_build04_fnce",
"man_build05",
"man_build05_al",
"man_build_int",
"man_chandeliers",
"man_f_chandelier",
"man_lights_pool",
"man_pool",
"man_safenewmny",
"man_scar_curtains",
"man_scar_props206",
"man_sdr_folge",
"man_sdr_rug",
"man_twr_stairs",
"man_twr_stairsB",
"man_xchandeliers",
"mansbushes",
"mansbushes2",
"mansion1b",
"mansionfence",
"marinafence01",
"marinafence02",
"marinafence03",
"marinafence04",
"marinafence05",
"marinaplanter1",
"marinaplanter2",
"marinaveg1",
"marinaveg2",
"marinaveg3",
"mc_fence1",
"mc_fence2",
"mc_fence3",
"mc_largebuild",
"mc_tower_01",
"mc_tower_02",
"mc_tower_03",
"mc_treesfw1_01",
"mc_treesfw2_01",
"mc_treesfw3_01",
"mc_wall",
"mc_wall2",
"mc_wall3",
"ml_planterbed",
"ml_vegbits01",
"ml_vegbits02",
"ml_vegbits03",
"ml_vegbits04",
"ml_vegbits05",
"mlmallbush",
"mn_treesis_int",
"mn_treesisl05",
"nbchflw01",
"nbchflw02",
"nbdcprmndfnc1",
"nbdcprmndfnc2",
"nbdecoshplants",
"nbeachbed01",
"nbeachbed02",
"nbeachbit03rails",
"nbeachvegy1",
"nbeachvegy2",
"nbecland12",
"nbecland12bball",
"nbecland12gates",
"nbt_balcony02",
"nbt_balcony03",
"nbt_balcony05",
"nbt_barfence01",
"nbt_hotel06balcony",
"nbt_hotel07fence",
"nbt_hoteltrees01",
"nbt_hoteltrees02",
"nbt_mansion01",
"nbt_mansion02",
"nbt_mansion03",
"nbt_mansion04",
"nbt_mansion0402",
"nbt_mansiontrees01",
"nbt_mansiontrees02",
"nbt_mansiontrees03",
"nbt_mansiontrees04",
"nbt_mansiontrees05",
"nbt_rooftopstart",
"nbthotel08fence02",
"nbw_bush01",
"nbw_bush02",
"nbwbusshy2",
"new_bushsm",
"new_bushtest",
"new_bushtest42",
"newbuild01",
"newbuild02",
"nhaitiplnt14",
"nhaitiplnt15",
"nrth1veg21",
"nrth1veg37",
"nrth1veg42",
"nrth3veg05",
"nrth3veg08",
"nrth3veg16",
"nrth3veg25",
"nrth3veg35",
"nrth3veg50",
"nrth3veg59",
"nrth4veg05",
"nrth4veg08",
"nrth4veg09",
"nrth4veg21",
"nrth4veg212",
"nrth7veg",
"nrth7veg09",
"nt_cablebox1_01",
"nt_cablebox2_01",
"nt_cablebox3_01",
"nt_cablebox4_01",
"nt_cablebox5_01",
"nt_cablebox6_01",
"od_alleys1_01_dy",
"od_alleys1_01_nt",
"od_alleys1b_01_dy",
"od_alleys1b_01_nt",
"od_alleys2_01_dy",
"od_alleys2_01_nt",
"od_alleys3_01_dy",
"od_alleys3_01_nt",
"od_alleys3b_01_dy",
"od_alleys3b_01_nt",
"od_bighotsign01",
"od_clevelfence",
"od_clubfence_dy",
"od_clubfence_nt",
"oddoorway",
"oddoorway2",
"oddoorwayS02",
"oddoorwayS1",
"odnvegbush1",
"odnvegbush2",
"odnvegbush2b",
"odnwiret",
"odrampbit",
"odrroofst02",
"odrroofst06",
"odrroofst07",
"odrv_bushes",
"odrv_bushes01",
"pierentrance02",
"plants01",
"plants04",
"plants05",
"plants05b",
"pw_backfence1",
"pw_bayfence2_01",
"rustship_structure0",
"scrapgate",
"sexgarden2",
"shipstairs",
"shpfrnts03rail01",
"shpfrnts03rail02",
"sjmgrass",
"sjmgrass2",
"spad_veg1",
"starbbnet02",
"starbitbush",
"starbits05",
"starbits06",
"starbits13",
"starbits13b",
"starbits13c",
"starbits17",
"starbits20",
"starbits22",
"starbits24",
"starbits45",
"starbits46",
"starbits49",
"starbits50",
"starbits51",
"starbits52",
"starbits54",
"starbits55",
"starbits56",
"starbits57",
"starbits58",
"starbits59",
"starblocks04",
"stardepot_FENCE",
"starfbed02",
"starfbed03",
"starfbed04",
"starfbed05",
"starfbed06",
"starsbush2",
"starwaterfrnt08",
"stationfence",
"stripinter",
"stripinterupside",
"striplights",
"svegrgedoor",
"tall_fence",
"telewire02",
"telewire03",
"telewire04",
"telgrphpole02",
"tesad06",
"tesad06sas",
"tesad06ss",
"veg_fern_balcny_kb1",
"veg_fern_balcny_kb2",
"veg_gaz",
"veg_ivy_balcny_kb3",
"veg_palm01",
"veg_palm02",
"veg_palm03",
"veg_palm04",
"veg_palmbig14",
"veg_palmkb1",
"veg_palmkb10",
"veg_palmkb13",
"veg_palmkb14",
"veg_palmkb1pERC",
"veg_palmkb2",
"veg_palmkb3",
"veg_palmkb4",
"veg_palmkb5",
"veg_palmkb7",
"veg_palmkb8",
"veg_palmkb9",
"veg_palmkbb11",
"veg_palwee01",
"veg_palwee02",
"veg_palwee03",
"veg_tree3",
"veg_treea1",
"veg_treea3",
"veg_treeb1",
"veged",
"veged01",
"veged02",
"vegeha1",
"vegetationb",
"vegetationb03",
"washbuild003",
"washbuild005",
"washbuild013",
"washbuild014",
"washbuild015",
"washbuild017",
"washbuild018",
"washbuild020",
"washbuild021",
"washbuild025",
"washbuild025neon",
"washbuild030",
"washbuild033",
"washbuild039",
"washbuild040",
"washbuild041",
"washbuild043",
"washbuild050",
"washbuild05067",
"washbuild058",
"washbuild062",
"washbuild063",
"washbuild066",
"washbuild068",
"washbuild069",
"washbuild071",
"washbuild072",
"washbuild073",
"washbuild074",
"washbuild075",
"washbuild081",
"washbuild0812",
"washbuild111",
"washbuild112",
"washbuild114",
"washbuild116",
"washbuild119",
"washbuild120",
"washbuild121",
"washbuild184",
"washbuild187",
"washbuild191",
"washbuild192",
"washbuild194",
"washbuild195",
"washbuild198",
"washbuild199",
"washbuild200",
"washbuild201",
"washbuild202",
"washbuild203",
"washbuild206",
"washbuild210",
"washbuild213",
"washbuild214",
"washbuild215",
"washbuild216",
"washbuild217",
"washbuild231",
"washelipad",
"washfence1",
"washfence2",
"washpshoutdet",
"washpshoutveg",
"washskyplant1",
"washskyplant2",
"washundermall1",
"washvegy2",
"washvegy237",
"washvegy238",
"washvegy239",
"washvegy240",
"washvegy241",
"washvegy2413",
"washvegy242",
"washvegy3",
"washvegy4",
"woshmallglas1",
"woshmallglas2",
"wsgbuildwl97",
"wshbuildws42",
"wshotelsign35",
"wshotelveg1",
"wshscarland226",
"wshtelgrphcabl01",
"wshtelgrphcabl02",
"wshtelgrphcabl03",
"wshtelgrphcabl04",
"wshtelgrphcabl05",
"wshtelgrphcabl06",
"wshtelgrphcabl07",
"wshtelgrphcabl08",
"wshtelgrphcabl09",
"wshtelgrphcabl10",
"wshtelgrphcabl11",
"xpolytrees1_dt",
"xpolytrees2_dt",
"xpolytrees3_dt",
"xpolytrees4_dt",
"",
};

View File

@@ -68,6 +68,9 @@ const CRGBA SCROLLBAR_COLOR = LABEL_COLOR;
#define MAX_VISIBLE_OPTION_ON_SCREEN (hasNativeList(m_nCurrScreen) ? MAX_VISIBLE_LIST_ROW : MAX_VISIBLE_OPTION)
#define SCREEN_HAS_AUTO_SCROLLBAR (m_nTotalListRow > MAX_VISIBLE_OPTION && !hasNativeList(m_nCurrScreen))
#define MIN_DRAWDIST 0.5f // default was 0.925f
#define MAX_DRAWDIST 1.8f
int GetOptionCount(int screen)
{
int i = 0;
@@ -729,10 +732,10 @@ CMenuManager::CheckSliderMovement(int value)
break;
case MENUACTION_DRAWDIST:
if(value > 0)
m_PrefsLOD += ((1.8f - 0.925f) / MENUSLIDER_LOGICAL_BARS);
m_PrefsLOD += ((MAX_DRAWDIST - MIN_DRAWDIST) / MENUSLIDER_LOGICAL_BARS);
else
m_PrefsLOD -= ((1.8f - 0.925f) / MENUSLIDER_LOGICAL_BARS);
m_PrefsLOD = Clamp(m_PrefsLOD, 0.925f, 1.8f);
m_PrefsLOD -= ((MAX_DRAWDIST - MIN_DRAWDIST) / MENUSLIDER_LOGICAL_BARS);
m_PrefsLOD = Clamp(m_PrefsLOD, MIN_DRAWDIST, MAX_DRAWDIST);
CRenderer::ms_lodDistScale = m_PrefsLOD;
break;
@@ -1562,7 +1565,7 @@ CMenuManager::DrawStandardMenus(bool activeScreen)
ProcessSlider(m_PrefsBrightness / 384.0f, SLIDER_Y(70.0f), HOVEROPTION_INCREASE_BRIGHTNESS, HOVEROPTION_DECREASE_BRIGHTNESS, SCREEN_WIDTH, true);
break;
case MENUACTION_DRAWDIST:
ProcessSlider((m_PrefsLOD - 0.925f) / 0.875f, SLIDER_Y(99.0f), HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, SCREEN_WIDTH, true);
ProcessSlider((m_PrefsLOD - MIN_DRAWDIST) / (MAX_DRAWDIST - MIN_DRAWDIST), SLIDER_Y(99.0f), HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, SCREEN_WIDTH, true);
break;
case MENUACTION_MUSICVOLUME:
if(m_nPrefsAudio3DProviderIndex != NO_AUDIO_PROVIDER)

View File

@@ -2026,6 +2026,10 @@ void CPad::Update(int16 pad)
NewState.RightStickY = 0;
NewState.RightShock = 0;
NewState.LeftShoulder1 = 0;
NewState.Cross = 0; // Added for safety
NewState.Triangle = 0; // Added for safety
NewState.Circle = 0; // Added for safety
NewState.Square = 0; // Added for safety
}
else
{
@@ -2048,8 +2052,13 @@ void CPad::Update(int16 pad)
NewState.RightStickX = state->joy2x;
NewState.RightStickY = state->joy2y;
NewState.RightShock = state->dpad_left;
NewState.LeftShoulder1 = (state->rtrig > 128 && state->ltrig > 128) ? 255 : 0;
// Add PS2-style A and B mappings, This may be the only solution for purchase items issue ?...
//Further more we can add other PS2 specific mapping here as certain `bool CPad::` functions are not available for mapping down below.
NewState.Cross = NewState.A; // A -> Cross (accept/purchase)
NewState.Triangle = NewState.B; // B -> Triangle (exit)
NewState.Circle = NewState.X; // Optional: X -> Circle
NewState.Square = NewState.Y; // Optional: Y -> Square
}
}
@@ -2076,6 +2085,10 @@ void CPad::Update(int16 pad)
NewState.RightStickY = 0;
NewState.RightShock = 0;
NewState.LeftShoulder1 = 0;
NewState.Cross = 0; // Added for safety
NewState.Triangle = 0; // Added for safety
NewState.Circle = 0; // Added for safety
NewState.Square = 0; // Added for safety
}
// if (old_contMaple == nullptr && contMaple != nullptr)
@@ -2132,12 +2145,12 @@ void CPad::Update(int16 pad)
if ( JustOutOfFrontend != 0 )
--JustOutOfFrontend;
#ifdef RW_DC
//auto old_contMaple = contMaple;
//auto n_dev = maple_enum_count();
contMaple = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
state = (cont_state_t *)maple_dev_status(contMaple);
#endif
}
void CPad::DoCheats(void)
@@ -3515,16 +3528,15 @@ bool CPad::CycleCameraModeJustDown(void)
bool result;
switch (CURMODE)
{
case 0:
case 2:
case 3:
case 0: //audible feedback when changing camera ?
{
result = !!(NewState.Select && !OldState.Select);
result = !!(NewState.DPadUp && !OldState.DPadUp);
break;
}
case 1:
case 1: //audible feedback when changing camera ?
{
result = !!(NewState.DPadUp && !OldState.DPadUp);
@@ -3541,9 +3553,9 @@ bool CPad::CycleCameraModeJustDown(void)
{
switch (CURMODE)
{
case 1:
case 1: //audible feedback when changing camera ?
{
result = !!(NewState.DPadDown && !OldState.DPadDown);
result = !!(NewState.DPadUp && !OldState.DPadUp);
break;
}
default:
@@ -3869,36 +3881,49 @@ bool CPad::CollectPickupJustDown(void)
return false;
}
bool CPad::DuckJustDown(void)
bool CPad::DuckJustDown(void)
{
if (ArePlayerControlsDisabled())
if (ArePlayerControlsDisabled()) {
duckFrameCounter = 0;
return false;
}
#ifdef RW_DC
switch (CPad::GetPad(0)->Mode)
{
case 0: //Xbox Mode
if (CPad::GetPad(0)->IsDualAnalog)
{
return !!(NewState.X&& !OldState.X);
}
else
{
return !!(NewState.X&& !OldState.X);
}
case 1: //PS2 Mode
if (CPad::GetPad(0)->IsDualAnalog)
{
return !!(NewState.X&& !OldState.X);
}
else
{
return !!(NewState.X&& !OldState.X);
}
bool buttonPressed = false;
switch (CPad::GetPad(0)->Mode) {
case 0: // Xbox Mode
buttonPressed = NewState.X;
break;
case 1: // PS2 Mode
buttonPressed = NewState.X;
break;
}
if (buttonPressed) {
duckFrameCounter++;
if (duckFrameCounter >= DUCK_DELAY_FRAMES && !isDucking) {
isDucking = true;
return true; // Trigger ducking after delay
}
} else {
duckFrameCounter = 0;
isDucking = false;
}
return false;
#else
return !!(NewState.LeftShock && !OldState.LeftShock);
bool buttonPressed = NewState.Square;
if (buttonPressed) {
duckFrameCounter++;
if (duckFrameCounter >= DUCK_DELAY_FRAMES && !isDucking) {
isDucking = true;
return true;
}
} else {
duckFrameCounter = 0;
isDucking = false;
}
return false;
#endif
}

View File

@@ -173,11 +173,26 @@ public:
uint32 CameraJustUpTime;
uint32 CameraLastPressed;
bool CameraIsDoublePressed;
static const int DUCK_DELAY_FRAMES = 30; // 1 second at 30 FPS
int duckFrameCounter; // Frames the duck button has been held
bool isDucking; // Tracks if duck action is active
#ifdef DETECT_PAD_INPUT_SWITCH
static bool IsAffectedByController;
static bool IsAffectedByController;
#endif
CPad() { }
CPad() : duckFrameCounter(0), isDucking(false), // New variables initialized
SteeringLeftRightBuffer{0}, DrunkDrivingBufferUsed(0), Phase(0), Mode(0),
ShakeDur(0), DisablePlayerControls(0), ShakeFreq(0), iCurrHornHistory(0),
JustOutOfFrontend(0), bApplyBrakes(0), LastTimeTouched(0), AverageWeapon(0),
AverageEntries(0), IsKeyboardMouse(false), IsDualAnalog(false),
CameraJustDown(false), CameraJustUp(false), CameraJustUpTime(0),
CameraLastPressed(0), CameraIsDoublePressed(false) {
Clear(false);
memset(bHornHistory, 0, sizeof(bHornHistory));
memset(CheatString, 0, sizeof(CheatString));
}
~CPad() { }
static bool bDisplayNoControllerMessage;

View File

@@ -1386,6 +1386,24 @@ bool re3EmergencyRemoveModel() {
return usedmem != CStreaming::ms_memoryUsed;
}
void* re3StreamingAlloc(size_t size) {
auto rv = RwMalloc(size);
while (rv == nil) {
if (re3RemoveLeastUsedModel()) {
rv = RwMalloc(size);
continue;
}
if (re3EmergencyRemoveModel()) {
rv = RwMalloc(size);
continue;
}
return nil;
}
return rv;
}
bool
CStreaming::RemoveLeastUsedModel(uint32 excludeMask)
{

View File

@@ -7,6 +7,8 @@
#pragma warning(disable: 4838) // narrowing conversion
#pragma warning(disable: 4996) // POSIX names
#include "src/common_defines.h"
#ifdef __MWERKS__
#define __STDC_LIMIT_MACROS // so we get UINT32_MAX etc
#endif

View File

@@ -59,6 +59,8 @@
#include <list>
#include "vmu/vmu.h"
#ifdef RWLIBS
extern "C" int vsprintf(char* const _Buffer, char const* const _Format, va_list _ArgList);
#endif
@@ -195,7 +197,13 @@ CustomFrontendOptionsPopulate(void)
#define MINI_CASE_SENSITIVE
#include "ini.h"
mINI::INIFile ini("reVC.ini");
mINI::INIFile ini(
#ifdef DC_SIM
"reVC.ini"
#else
"/vmu/" VMU_DEFAULT_PATH "/reVCini"
#endif
);
mINI::INIStructure cfg;
bool ReadIniIfExists(const char *cat, const char *key, uint32 *out)
@@ -483,13 +491,19 @@ void SaveINIControllerSettings()
#endif
StoreIni("Controller", "PadButtonsInited", ControlsManager.ms_padButtonsInited);
ini.write(cfg);
{
RAIIVmuBeep(VMU_DEFAULT_PATH, 1.0f);
ini.write(cfg);
}
}
bool LoadINISettings()
{
if (!ini.read(cfg))
return false;
{
RAIIVmuBeep(VMU_DEFAULT_PATH, 1.0f);
if (!ini.read(cfg))
return false;
}
#ifdef IMPROVED_VIDEOMODE
ReadIniIfExists("VideoMode", "Width", &FrontEndMenuManager.m_nPrefsWidth);

View File

@@ -94,6 +94,10 @@
#include <sys/stat.h>
#include <cctype>
#ifdef DC_SH4
#include <dc/vmu_pkg.h>
#endif
namespace mINI
{
namespace INIStringUtil
@@ -335,6 +339,7 @@ namespace mINI
private:
std::ifstream fileReadStream;
T_LineDataPtr lineData;
std::size_t start_offt;
T_LineData readFile()
{
@@ -343,7 +348,7 @@ namespace mINI
fileContents.resize(fileReadStream.tellg());
fileReadStream.seekg(0, std::ios::beg);
std::size_t fileSize = fileContents.size();
fileReadStream.read(&fileContents[0], fileSize);
fileReadStream.read(const_cast<char *>(fileContents.c_str()), fileSize);
fileReadStream.close();
T_LineData output;
if (fileSize == 0)
@@ -352,7 +357,19 @@ namespace mINI
}
std::string buffer;
buffer.reserve(50);
for (std::size_t i = 0; i < fileSize; ++i)
#ifdef DC_SH4
{
vmu_pkg_t vmu_pkg;
if(vmu_pkg_parse(reinterpret_cast<uint8*>(const_cast<int8*>(fileContents.c_str())), &vmu_pkg) != 0) {
// If we failed to parse, we assume it's raw with no VMS header.
start_offt = 0;
} else {
start_offt = reinterpret_cast<unsigned int>(vmu_pkg.data)
- reinterpret_cast<unsigned int>(fileContents.c_str());
}
}
#endif
for (std::size_t i = start_offt; i < fileSize; ++i)
{
char& c = fileContents[i];
if (c == '\n')
@@ -378,6 +395,8 @@ namespace mINI
{
lineData = std::make_shared<T_LineData>();
}
start_offt = 0;
}
~INIReader() { }
@@ -426,22 +445,71 @@ namespace mINI
{
private:
std::ofstream fileWriteStream;
std::stringstream memStream;
inline static std::ios_base::iostate lastError_;
public:
bool prettyPrint = false;
INIGenerator(std::string const& filename)
INIGenerator(std::string const& filename, bool prettyPrint_=false)
: fileWriteStream(filename, std::ios::out | std::ios::binary),
prettyPrint(prettyPrint_)
{
fileWriteStream.open(filename, std::ios::out | std::ios::binary);
lastError_ = fileWriteStream.rdstate();
}
~INIGenerator()
{
if(!fileWriteStream.good()) {
return;
}
std::string str = memStream.str();
const char *buf = str.c_str();
int buf_size = memStream.tellp();
#ifdef DC_SH4
uint8_t *data;
uint8_t icon_buf[512 * 1];
vmu_pkg_t vmu_pkg = {
.desc_short = "DCA-M Config",
.desc_long = "DCA-M Settings File",
.app_id = "The Gang",
.icon_cnt = 1,
.icon_anim_speed = 0,
.data_len = buf_size,
.icon_data = icon_buf,
.data = reinterpret_cast<const uint8_t*>(buf),
};
if (vmu_pkg_load_icon(&vmu_pkg, "settings.ico") < 0) {
vmu_pkg.icon_cnt = 0;
}
if(vmu_pkg_build(&vmu_pkg, &data, &buf_size) < 0) {
lastError_ = std::ios_base::badbit;
return;
}
buf = reinterpret_cast<char*>(data);
#endif
fileWriteStream.write(buf, buf_size);
lastError_ = fileWriteStream.rdstate();
#ifdef DC_SH4
// Must free the internal buffer allocated by vmu_pkg_build().
free(data);
#endif
}
bool operator<<(const std::string& str)
{
memStream << str;
return true;
}
~INIGenerator() { }
bool operator<<(INIStructure const& data)
{
if (!fileWriteStream.is_open())
{
return false;
}
if (!data.size())
{
return true;
@@ -451,13 +519,13 @@ namespace mINI
{
auto const& section = it->first;
auto const& collection = it->second;
fileWriteStream
memStream
<< "["
<< section
<< "]";
if (collection.size())
{
fileWriteStream << INIStringUtil::endl;
memStream << INIStringUtil::endl;
auto it2 = collection.begin();
for (;;)
{
@@ -465,7 +533,7 @@ namespace mINI
INIStringUtil::replace(key, "=", "\\=");
auto value = it2->second;
INIStringUtil::trim(value);
fileWriteStream
memStream
<< key
<< ((prettyPrint) ? " = " : "=")
<< value;
@@ -473,21 +541,29 @@ namespace mINI
{
break;
}
fileWriteStream << INIStringUtil::endl;
memStream << INIStringUtil::endl;
}
}
if (++it == data.end())
{
break;
}
fileWriteStream << INIStringUtil::endl;
memStream << INIStringUtil::endl;
if (prettyPrint)
{
fileWriteStream << INIStringUtil::endl;
memStream << INIStringUtil::endl;
}
}
return true;
}
operator bool() const
{
return fileWriteStream.rdstate() == fileWriteStream.goodbit;
}
static std::ios_base::iostate lastError() { return lastError_; }
static bool wasGood() { return lastError_ == std::ios_base::goodbit; }
};
class INIWriter
@@ -667,12 +743,15 @@ namespace mINI
{
struct stat buf;
bool fileExists = (stat(filename.c_str(), &buf) == 0);
if (!fileExists)
{
INIGenerator generator(filename);
generator.prettyPrint = prettyPrint;
return generator << data;
if(INIGenerator generator(filename, prettyPrint); generator) {
generator << data;
}
return INIGenerator::wasGood();
}
INIStructure originalData;
T_LineDataPtr lineData;
bool readSuccess = false;
@@ -688,23 +767,21 @@ namespace mINI
return false;
}
T_LineData output = getLazyOutput(lineData, data, originalData);
std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
if (fileWriteStream.is_open())
{
if (output.size())
if (INIGenerator generator(filename, prettyPrint); generator && output.size())
{
auto line = output.begin();
for (;;)
{
fileWriteStream << *line;
generator << *line;
if (++line == output.end())
{
break;
}
fileWriteStream << INIStringUtil::endl;
generator << INIStringUtil::endl;
}
}
return true;
return INIGenerator::wasGood();
}
return false;
}
@@ -741,9 +818,10 @@ namespace mINI
{
return false;
}
INIGenerator generator(filename);
generator.prettyPrint = pretty;
return generator << data;
if(INIGenerator generator(filename, pretty); generator) {
generator << data;
}
return INIGenerator::wasGood();
}
bool write(INIStructure& data, bool pretty = false) const
{

View File

@@ -1,11 +1,5 @@
#include "common.h"
CMatrix::CMatrix(void)
{
m_attachment = nil;
m_hasRwMatrix = false;
}
CMatrix::CMatrix(CMatrix const &m)
{
m_attachment = nil;
@@ -434,6 +428,11 @@ operator*(const CMatrix &m1, const CMatrix &m2)
{
// TODO: VU0 code
CMatrix out;
#if defined(RW_DC)
mat_load(reinterpret_cast<const matrix_t *>(&m1));
mat_apply(reinterpret_cast<const matrix_t *>(&m2));
mat_store(reinterpret_cast<matrix_t *>(&out));
#else
out.rx = m1.rx * m2.rx + m1.fx * m2.ry + m1.ux * m2.rz;
out.ry = m1.ry * m2.rx + m1.fy * m2.ry + m1.uy * m2.rz;
out.rz = m1.rz * m2.rx + m1.fz * m2.ry + m1.uz * m2.rz;
@@ -446,6 +445,7 @@ operator*(const CMatrix &m1, const CMatrix &m2)
out.px = m1.rx * m2.px + m1.fx * m2.py + m1.ux * m2.pz + m1.px;
out.py = m1.ry * m2.px + m1.fy * m2.py + m1.uy * m2.pz + m1.py;
out.pz = m1.rz * m2.px + m1.fz * m2.py + m1.uz * m2.pz + m1.pz;
#endif
return out;
}

View File

@@ -1,6 +1,6 @@
#pragma once
class CMatrix
class alignas(8) CMatrix
{
public:
#ifdef GTA_PS2
@@ -23,18 +23,18 @@ public:
float f[4][4];
struct
{
float rx, ry, rz, rw;
float fx, fy, fz, fw;
float ux, uy, uz, uw;
float px, py, pz, pw;
float rx, ry, rz, rw=0.0f;
float fx, fy, fz, fw=0.0f;
float ux, uy, uz, uw=0.0f;
float px, py, pz, pw=1.0f;
};
};
RwMatrix *m_attachment;
bool m_hasRwMatrix; // are we the owner?
RwMatrix *m_attachment=nil;
bool m_hasRwMatrix=false; // are we the owner?
#endif
CMatrix(void);
CMatrix(void) {}
CMatrix(CMatrix const &m);
CMatrix(RwMatrix *matrix, bool owner = false);
CMatrix(float scale){

View File

@@ -1,6 +1,14 @@
#pragma once
class TYPEALIGN(16) CVuVector : public CVector
#include "maths.h"
#ifdef RW_DC
#define VECTOR_ALIGN 8
#else
#define VECTOR_ALIGN 16
#endif
class TYPEALIGN(VECTOR_ALIGN) CVuVector : public CVector
{
public:
float w;
@@ -26,7 +34,123 @@ public:
// TODO: operator-
};
void TransformPoint(CVuVector &out, const CMatrix &mat, const CVuVector &in);
void TransformPoint(CVuVector &out, const CMatrix &mat, const RwV3d &in);
void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride);
void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const CVuVector *in);
__always_inline void TransformPoint(CVuVector &out, const CMatrix &mat, const CVuVector &in)
{
#ifdef GTA_PS2
__asm__ __volatile__("\n\
lqc2 vf01,0x0(%2)\n\
lqc2 vf02,0x0(%1)\n\
lqc2 vf03,0x10(%1)\n\
lqc2 vf04,0x20(%1)\n\
lqc2 vf05,0x30(%1)\n\
vmulax.xyz ACC, vf02,vf01\n\
vmadday.xyz ACC, vf03,vf01\n\
vmaddaz.xyz ACC, vf04,vf01\n\
vmaddw.xyz vf06,vf05,vf00\n\
sqc2 vf06,0x0(%0)\n\
": : "r" (&out) , "r" (&mat) ,"r" (&in): "memory");
#elif defined(DC_SH4)
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&mat)));
mat_trans_single3_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z);
#else
out = mat * in;
#endif
}
__always_inline void TransformPoint(CVuVector &out, const CMatrix &mat, const RwV3d &in)
{
#ifdef GTA_PS2
__asm__ __volatile__("\n\
ldr $8,0x0(%2)\n\
ldl $8,0x7(%2)\n\
lw $9,0x8(%2)\n\
pcpyld $10,$9,$8\n\
qmtc2 $10,vf01\n\
lqc2 vf02,0x0(%1)\n\
lqc2 vf03,0x10(%1)\n\
lqc2 vf04,0x20(%1)\n\
lqc2 vf05,0x30(%1)\n\
vmulax.xyz ACC, vf02,vf01\n\
vmadday.xyz ACC, vf03,vf01\n\
vmaddaz.xyz ACC, vf04,vf01\n\
vmaddw.xyz vf06,vf05,vf00\n\
sqc2 vf06,0x0(%0)\n\
": : "r" (&out) , "r" (&mat) ,"r" (&in): "memory");
#elif defined(DC_SH4)
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&mat)));
mat_trans_single3_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z);
#else
out = mat * in;
#endif
}
__always_inline void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride)
{
#ifdef GTA_PS3
__asm__ __volatile__("\n\
paddub $3,%4,$0\n\
lqc2 vf02,0x0(%2)\n\
lqc2 vf03,0x10(%2)\n\
lqc2 vf04,0x20(%2)\n\
lqc2 vf05,0x30(%2)\n\
ldr $8,0x0(%3)\n\
ldl $8,0x7(%3)\n\
lw $9,0x8(%3)\n\
pcpyld $10,$9,$8\n\
qmtc2 $10,vf01\n\
1: vmulax.xyz ACC, vf02,vf01\n\
vmadday.xyz ACC, vf03,vf01\n\
vmaddaz.xyz ACC, vf04,vf01\n\
vmaddw.xyz vf06,vf05,vf00\n\
add %3,%3,$3\n\
ldr $8,0x0(%3)\n\
ldl $8,0x7(%3)\n\
lw $9,0x8(%3)\n\
pcpyld $10,$9,$8\n\
qmtc2 $10,vf01\n\
addi %1,%1,-1\n\
addiu %0,%0,0x10\n\
sqc2 vf06,-0x10(%0)\n\
bnez %1,1b\n\
": : "r" (out) , "r" (n), "r" (&mat), "r" (in), "r" (stride): "memory");
#elif defined(DC_SH4)
mat_load(reinterpret_cast<matrix_t *>(const_cast<CMatrix *>(&mat)));
while(n--) {
mat_trans_single3_nodiv_nomod(in->x, in->y, in->z, out->x, out->y, out->z);
in = reinterpret_cast<const RwV3d *>(reinterpret_cast<const uint8_t *>(in) + stride);
++out;
}
#else
while(n--){
*out = mat * *in;
in = (RwV3d*)((uint8*)in + stride);
out++;
}
#endif
}
__always_inline void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const CVuVector *in)
{
#ifdef GTA_PS2
__asm__ __volatile__("\n\
lqc2 vf02,0x0(%2)\n\
lqc2 vf03,0x10(%2)\n\
lqc2 vf04,0x20(%2)\n\
lqc2 vf05,0x30(%2)\n\
lqc2 vf01,0x0(%3)\n\
nop\n\
1: vmulax.xyz ACC, vf02,vf01\n\
vmadday.xyz ACC, vf03,vf01\n\
vmaddaz.xyz ACC, vf04,vf01\n\
vmaddw.xyz vf06,vf05,vf00\n\
lqc2 vf01,0x10(%3)\n\
addiu %3,%3,0x10\n\
addi %1,%1,-1\n\
addiu %0,%0,0x10\n\
sqc2 vf06,-0x10(%0)\n\
bnez %1,1b\n\
": : "r" (out) , "r" (n), "r" (&mat) ,"r" (in): "memory");
#else
TransformPoints(out, n, mat, in, sizeof(CVuVector));
#endif
}

View File

@@ -3,116 +3,3 @@
#include "VuVector.h"
// TODO: move more stuff into here
void TransformPoint(CVuVector &out, const CMatrix &mat, const CVuVector &in)
{
#ifdef GTA_PS2
__asm__ __volatile__("\n\
lqc2 vf01,0x0(%2)\n\
lqc2 vf02,0x0(%1)\n\
lqc2 vf03,0x10(%1)\n\
lqc2 vf04,0x20(%1)\n\
lqc2 vf05,0x30(%1)\n\
vmulax.xyz ACC, vf02,vf01\n\
vmadday.xyz ACC, vf03,vf01\n\
vmaddaz.xyz ACC, vf04,vf01\n\
vmaddw.xyz vf06,vf05,vf00\n\
sqc2 vf06,0x0(%0)\n\
": : "r" (&out) , "r" (&mat) ,"r" (&in): "memory");
#else
out = mat * in;
#endif
}
void TransformPoint(CVuVector &out, const CMatrix &mat, const RwV3d &in)
{
#ifdef GTA_PS2
__asm__ __volatile__("\n\
ldr $8,0x0(%2)\n\
ldl $8,0x7(%2)\n\
lw $9,0x8(%2)\n\
pcpyld $10,$9,$8\n\
qmtc2 $10,vf01\n\
lqc2 vf02,0x0(%1)\n\
lqc2 vf03,0x10(%1)\n\
lqc2 vf04,0x20(%1)\n\
lqc2 vf05,0x30(%1)\n\
vmulax.xyz ACC, vf02,vf01\n\
vmadday.xyz ACC, vf03,vf01\n\
vmaddaz.xyz ACC, vf04,vf01\n\
vmaddw.xyz vf06,vf05,vf00\n\
sqc2 vf06,0x0(%0)\n\
": : "r" (&out) , "r" (&mat) ,"r" (&in): "memory");
#else
out = mat * in;
#endif
}
void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const RwV3d *in, int stride)
{
#ifdef GTA_PS3
__asm__ __volatile__("\n\
paddub $3,%4,$0\n\
lqc2 vf02,0x0(%2)\n\
lqc2 vf03,0x10(%2)\n\
lqc2 vf04,0x20(%2)\n\
lqc2 vf05,0x30(%2)\n\
ldr $8,0x0(%3)\n\
ldl $8,0x7(%3)\n\
lw $9,0x8(%3)\n\
pcpyld $10,$9,$8\n\
qmtc2 $10,vf01\n\
1: vmulax.xyz ACC, vf02,vf01\n\
vmadday.xyz ACC, vf03,vf01\n\
vmaddaz.xyz ACC, vf04,vf01\n\
vmaddw.xyz vf06,vf05,vf00\n\
add %3,%3,$3\n\
ldr $8,0x0(%3)\n\
ldl $8,0x7(%3)\n\
lw $9,0x8(%3)\n\
pcpyld $10,$9,$8\n\
qmtc2 $10,vf01\n\
addi %1,%1,-1\n\
addiu %0,%0,0x10\n\
sqc2 vf06,-0x10(%0)\n\
bnez %1,1b\n\
": : "r" (out) , "r" (n), "r" (&mat), "r" (in), "r" (stride): "memory");
#else
while(n--){
*out = mat * *in;
in = (RwV3d*)((uint8*)in + stride);
out++;
}
#endif
}
void TransformPoints(CVuVector *out, int n, const CMatrix &mat, const CVuVector *in)
{
#ifdef GTA_PS2
__asm__ __volatile__("\n\
lqc2 vf02,0x0(%2)\n\
lqc2 vf03,0x10(%2)\n\
lqc2 vf04,0x20(%2)\n\
lqc2 vf05,0x30(%2)\n\
lqc2 vf01,0x0(%3)\n\
nop\n\
1: vmulax.xyz ACC, vf02,vf01\n\
vmadday.xyz ACC, vf03,vf01\n\
vmaddaz.xyz ACC, vf04,vf01\n\
vmaddw.xyz vf06,vf05,vf00\n\
lqc2 vf01,0x10(%3)\n\
addiu %3,%3,0x10\n\
addi %1,%1,-1\n\
addiu %0,%0,0x10\n\
sqc2 vf06,-0x10(%0)\n\
bnez %1,1b\n\
": : "r" (out) , "r" (n), "r" (&mat) ,"r" (in): "memory");
#else
while(n--){
*out = mat * *in;
in++;
out++;
}
#endif
}

View File

@@ -1,5 +1,32 @@
#pragma once
#include "src/common_defines.h"
#include <dc/matrix.h>
#ifdef DC_SH4
#define mat_trans_nodiv_nomod(x, y, z, x2, y2, z2, w2) do { \
register float __x __asm__("fr12") = (x); \
register float __y __asm__("fr13") = (y); \
register float __z __asm__("fr14") = (z); \
register float __w __asm__("fr15") = 1.0f; \
__asm__ __volatile__( "ftrv xmtrx, fv12\n" \
: "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w) \
: "0" (__x), "1" (__y), "2" (__z), "3" (__w) ); \
x2 = __x; y2 = __y; z2 = __z; w2 = __w; \
} while(false)
#else
#define mat_trans_nodiv_nomod(x_, y_, z_, x2, y2, z2, w2) do { \
vector_t tmp = { x_, y_, z_, 1.0f }; \
mat_transform(&tmp, &tmp, 1, 0); \
x2 = tmp.x; y2 = tmp.y; z2 = tmp.z; w2 = tmp.w; \
} while(false)
#endif
// wrapper around float versions of functions
// in gta they are in CMaths but that makes the code rather noisy

View File

@@ -40,6 +40,14 @@ CBaseModelInfo::DeleteCollisionModel(void)
}
}
void CBaseModelInfo::SetColModel(CColModel *col, bool owns) {
if (m_bOwnsColModel) {
delete m_colModel;
}
m_colModel = col;
m_bOwnsColModel = owns;
}
void
CBaseModelInfo::AddRef(void)
{

View File

@@ -52,8 +52,7 @@ public:
bool IsClump(void) { return m_type == MITYPE_CLUMP || m_type == MITYPE_PED || m_type == MITYPE_VEHICLE; }
char *GetModelName(void) { return m_name; }
void SetModelName(const char *name) { strncpy(m_name, name, MAX_MODEL_NAME); }
void SetColModel(CColModel *col, bool owns = false){
m_colModel = col; m_bOwnsColModel = owns; }
void SetColModel(CColModel *col, bool owns = false);
CColModel *GetColModel(void) { return m_colModel; }
bool DoesOwnColModel(void) { return m_bOwnsColModel; }
void DeleteCollisionModel(void);

View File

@@ -271,13 +271,13 @@ CShadowCamera::InvertRaster()
RwIm2DVertexSetIntRGBA (&vx[1], 255, 255, 255, 255);
RwIm2DVertexSetScreenX (&vx[2], crw);
RwIm2DVertexSetScreenY (&vx[2], 0.0f);
RwIm2DVertexSetScreenY (&vx[2], crh);
RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ());
RwIm2DVertexSetRecipCameraZ(&vx[2], recipZ);
RwIm2DVertexSetIntRGBA (&vx[2], 255, 255, 255, 255);
RwIm2DVertexSetScreenX (&vx[3], crw);
RwIm2DVertexSetScreenY (&vx[3], crh);
RwIm2DVertexSetScreenY (&vx[3], 0.0f);
RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ());
RwIm2DVertexSetRecipCameraZ(&vx[3], recipZ);
RwIm2DVertexSetIntRGBA (&vx[3], 255, 255, 255, 255);
@@ -289,7 +289,7 @@ CShadowCamera::InvertRaster()
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO);
RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, vx, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA);

View File

@@ -60,7 +60,11 @@ public:
};
enum {
#ifdef RW_DC
NUM_RAIN_STREAKS = 10
#elif
NUM_RAIN_STREAKS = 35
#endif
};
struct tRainStreak

View File

@@ -384,23 +384,23 @@ RwBool Im2DRenderQuad(RwReal x1, RwReal y1, RwReal x2, RwReal y2, RwReal z, RwRe
RwIm2DVertexSetU(&vx[1], uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[1], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetScreenX(&vx[2], x2);
RwIm2DVertexSetScreenY(&vx[2], y1);
RwIm2DVertexSetScreenX(&vx[2], x2);
RwIm2DVertexSetScreenY(&vx[2], y2);
RwIm2DVertexSetScreenZ(&vx[2], z);
RwIm2DVertexSetIntRGBA(&vx[2], 255, 255, 255, 255);
RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ);
RwIm2DVertexSetU(&vx[2], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[2], uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[2], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetScreenX(&vx[3], x2);
RwIm2DVertexSetScreenY(&vx[3], y2);
RwIm2DVertexSetScreenY(&vx[3], y1);
RwIm2DVertexSetScreenZ(&vx[3], z);
RwIm2DVertexSetIntRGBA(&vx[3], 255, 255, 255, 255);
RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ);
RwIm2DVertexSetU(&vx[3], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[3], 1.0f + uvOffset, recipCamZ);
RwIm2DVertexSetV(&vx[3], uvOffset, recipCamZ);
RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4);
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, vx, 4);
return TRUE;
}

View File

@@ -17,6 +17,8 @@
#include "vmu/vmu.h"
void* re3StreamingAlloc(size_t size);
const char* _psGetUserFilesFolder();
C_PcSave PcSaveHelper;
@@ -76,31 +78,37 @@ C_PcSave::SaveSlot(int32 slot)
bool
C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
{
void* wrkmem = malloc(LZO1X_1_MEM_COMPRESS);
uint8* compressed = (uint8*)malloc(size*2);
void* wrkmem = re3StreamingAlloc(LZO1X_1_MEM_COMPRESS);
assert(wrkmem);
uint8* compressed = (uint8*)re3StreamingAlloc(size*2);
assert(compressed);
lzo_uint compressed_size;
int crv = lzo1x_1_compress(data, size, compressed, &compressed_size, wrkmem);
free(wrkmem);
RwFree(wrkmem);
if (crv == LZO_E_OK && compressed_size >= size) {
crv = LZO_E_NOT_COMPRESSIBLE;
}
if (crv == LZO_E_OK) {
uint32_t compressed_size32 = compressed_size | 0x80000000;
bool err = CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)) != sizeof(compressed_size32);
if (err || CFileMgr::GetErrorReadWrite(file)) {
free(compressed);
RwFree(compressed);
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false;
}
err = CFileMgr::Write(file, (const char*)compressed, compressed_size) != compressed_size;
free(compressed);
RwFree(compressed);
if (err || CFileMgr::GetErrorReadWrite(file)) {
nErrorCode = SAVESTATUS_ERR_SAVE_WRITE;
strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1);
return false;
}
} else if (crv == LZO_E_NOT_COMPRESSIBLE) {
free(compressed);
RwFree(compressed);
uint32_t compressed_size32 = size;
bool err = CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)) != sizeof(compressed_size32);
if (err || CFileMgr::GetErrorReadWrite(file)) {
@@ -115,7 +123,7 @@ C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size)
return false;
}
} else {
free(compressed);
RwFree(compressed);
return false;
}
@@ -153,16 +161,17 @@ uint32_t C_PcSave::PcClassLoadRoutine(int32 file, uint8 *data) {
return size;
} else {
size &= ~0x80000000;
uint8* compressed = (uint8*)malloc(size);
uint8* compressed = (uint8*)re3StreamingAlloc(size);
assert(compressed);
err = CFileMgr::Read(file, (const char*)compressed, size) != size;
if (err || CFileMgr::GetErrorReadWrite(file)) {
free(compressed);
RwFree(compressed);
return 0;
}
lzo_uint decompressed_size = 0;
auto crv = lzo1x_decompress(compressed, size, data, &decompressed_size, NULL);
free(compressed);
RwFree(compressed);
if (crv != LZO_E_OK) {
return 0;
}

View File

@@ -53,6 +53,9 @@ uint32_t pvr_map32(uint32_t offset32) {return 0;}
void Hackpresent() { }
void re3RemoveLeastUsedModel() { assert(false); }
void re3EmergencyRemoveModel() { assert(false); }
void* re3StreamingAlloc(size_t sz) {
return RwMalloc(sz);
}
void RwTexDictionaryGtaStreamRead1(rw::Stream*){ assert(false); }
void RwTexDictionaryGtaStreamRead2(rw::Stream*, rw::TexDictionary*) { assert(false); }
void pvr_ta_data(void* data, int size) {

View File

@@ -125,6 +125,8 @@ void x11_window_create()
x11_win = (void*)x11Window;
x11_vis = (void*)x11Visual->visual;
delete x11Visual;
x11_window_set_text("GTA3dc");
}

View File

@@ -221,6 +221,7 @@ AnimInterpolator::setCurrentAnim(Animation *anim)
{
int32 i;
AnimInterpolatorInfo *interpInfo = anim->interpInfo;
assert(this->currentAnim == nil || this->currentAnim == anim);
this->currentAnim = anim;
this->currentTime = 0.0f;
int32 maxkf = this->maxInterpKeyFrameSize;

File diff suppressed because it is too large Load Diff