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
59 changed files with 2171 additions and 1307 deletions

1
.gitignore vendored
View File

@@ -379,7 +379,6 @@ liberty/texconv*
liberty/imgtool*
liberty/coltool*
liberty/streamheaderpack*
liberty/merge-palettes*
liberty/extract-sfx*
liberty/pack-sfx*
liberty/analyze-profile*

View File

@@ -146,9 +146,6 @@
"coroutine": "cpp",
"future": "cpp",
"latch": "cpp",
"syncstream": "cpp",
"mycommon.h": "c",
"file_tex.h": "c",
"optparse.h": "c"
"syncstream": "cpp"
}
}

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
@@ -33,9 +33,6 @@ REPACK_STREAM_DECODED_DIR?=$(REPACK_DIR)/stream-decoded
REPACK_STREAM_DEST_DIR=$(REPACK_GTA_DIR)/stream
REPACK_CUTS_ORIG_DIR?=$(REPACK_DIR)/cuts-orig
REPACK_CUTS_DC_DIR?=$(REPACK_DIR)/cuts-dc
REPACK_MISC_TXD_EXTRACT_DIR?=$(REPACK_DIR)/misc-extract
REPACK_TEXTURES_DIR?=$(REPACK_DIR)/textures
REPACK_TEXTURE_CLUSTERS_DIR?=$(REPACK_DIR)/texture-clusters
LIBS :=
TEXCONV_FLAGS :=
@@ -186,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
@@ -201,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
@@ -225,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)
@@ -244,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
@@ -307,16 +312,16 @@ coltool: ../src/tools/coltool.cpp
streamheaderpack: ../src/tools/streamheaderpack.cpp
$(CXX) -std=c++17 -o $@ -g -O0 $<
merge-palettes: ../src/tools/merge-palettes.cpp
$(CXX) -std=c++17 -o $@ -g -O0 $<
-include $(DEPS)
#### Repacking ####
TXD_OPTS_fonts = 512 512
TXD_OPTS_hud = 512 512
TXD_OPTS_menu = 512 512
TXD_OPTS_fonts = 256 256
TXD_OPTS_hud = 128 128
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
@@ -364,15 +369,12 @@ TXD_OPTS_frontend = 512 512 \
--include-tex assets/ps4_f.png ps4_f \
--include-tex assets/xbox_d.png xbox_d \
--include-tex assets/xbox_f.png xbox_f
TXD_OPTS_generic = 512 512
TXD_OPTS_MISC = 512 512
TXD_OPTS_particle = 512 512
DEFAULT_RES = 512
PVR_ENCODER ?= PVRTEX
TEXTURE_DOWNSAMPLE_TXD ?= NONE
TEXTURE_DOWNSAMPLE_IMG ?= NONE
TEXTURE_DOWNSAMPLE_IMG ?= HALF
-include texlist.mk
-include modlist.mk
@@ -400,11 +402,6 @@ STREAM_ADPCM_DC = $(addprefix $(REPACK_STREAM_DEST_DIR)/, $(STREAM_WAV:.wav=.APM
IMG_TEXTURES_ORIG = $(addprefix $(REPACK_IMG_ORIG_DIR)/, $(IMG_TEXTURES))
IMG_MODELS_ORIG = $(addprefix $(REPACK_IMG_ORIG_DIR)/, $(IMG_MODELS))
ALL_TEXTURES_ORIG = $(addprefix $(GTA_DIR)/,$(MISC_TXD)) $(IMG_TEXTURES_ORIG)
ALL_TEXTURES_EXTRACT_PATH = $(addprefix $(REPACK_MISC_TXD_EXTRACT_DIR)/,$(MISC_TXD)) $(IMG_TEXTURES_ORIG)
ALL_TEXTURES_ORIG_EXTRACT_txd = $(ALL_TEXTURES_EXTRACT_PATH:.txd=.extract)
ALL_TEXTURES_ORIG_EXTRACT = $(ALL_TEXTURES_ORIG_EXTRACT_txd:.TXD=.extract)
CUTS_IFP_ORIG = $(addprefix $(REPACK_CUTS_ORIG_DIR)/, $(CUTS_IFP))
CUTS_MISC_ORIG = $(addprefix $(REPACK_CUTS_ORIG_DIR)/, $(CUTS_MISC))
@@ -415,85 +412,12 @@ SFX_REPACK_DC = $(SFX_REPACK_DC_WAV:.wav=.pcm)
STREAM_MP3_DECODED = $(addprefix $(REPACK_STREAM_DECODED_DIR)/, $(STREAM_MP3:.mp3=.wav))
STREAM_WAV_DECODED = $(addprefix $(REPACK_STREAM_DECODED_DIR)/, $(STREAM_WAV))
.PRECIOUS: $(SFX_ORIG) $(SFX_REPACK_DC) $(STREAM_MP3_DECODED) $(STREAM_WAV_DECODED) $(ALL_TEXTURES_ORIG_EXTRACT)
.PRECIOUS: $(SFX_ORIG) $(SFX_REPACK_DC) $(STREAM_MP3_DECODED) $(STREAM_WAV_DECODED)
# extracting textures from .txd
# loose, gamefiles
$(REPACK_MISC_TXD_EXTRACT_DIR)/%.extract: $(GTA_GAMEFILES_LOOSE_DIR)/%.TXD texconv
@rm -rf $(basename $@).contents
@mkdir -p $(basename $@).contents
@mkdir -p $(REPACK_TEXTURES_DIR)
./texconv $< $(basename $@) $(TXD_OPTS_$(notdir $*)) -e extract
@touch $@
$(REPACK_MISC_TXD_EXTRACT_DIR)/%.extract: $(GTA_GAMEFILES_LOOSE_DIR)/%.txd texconv
@rm -rf $(basename $@).contents
@mkdir -p $(basename $@).contents
@mkdir -p $(REPACK_TEXTURES_DIR)
./texconv $< $(basename $@) $(TXD_OPTS_$(notdir $*)) -e extract
@touch $@
# loose, originals
$(REPACK_MISC_TXD_EXTRACT_DIR)/%.extract: $(GTA_DIR)/%.TXD texconv
@rm -rf $(basename $@).contents
@mkdir -p $(basename $@).contents
@mkdir -p $(REPACK_TEXTURES_DIR)
./texconv $< $(basename $@) $(TXD_OPTS_$(notdir $*)) -e extract
@touch $@
$(REPACK_MISC_TXD_EXTRACT_DIR)/%.extract: $(GTA_DIR)/%.txd texconv
@rm -rf $(basename $@).contents
@mkdir -p $(basename $@).contents
@mkdir -p $(REPACK_TEXTURES_DIR)
./texconv $< $(basename $@) $(TXD_OPTS_$(notdir $*)) -e extract
@touch $@
# img files
$(REPACK_IMG_ORIG_DIR)/%.extract: $(REPACK_IMG_ORIG_DIR)/%.TXD texconv
@rm -rf $(basename $@).contents
@mkdir -p $(basename $@).contents
@mkdir -p $(REPACK_TEXTURES_DIR)
./texconv $< $(basename $@) 1024 1024 -e extract
@touch $@
$(REPACK_IMG_ORIG_DIR)/%.extract: $(REPACK_IMG_ORIG_DIR)/%.txd texconv
@rm -rf $(basename $@).contents
@mkdir -p $(basename $@).contents
@mkdir -p $(REPACK_TEXTURES_DIR)
./texconv $< $(basename $@) 1024 1024 -e extract
@touch $@
$(REPACK_DIR)/extracted: $(ALL_TEXTURES_ORIG_EXTRACT)
echo && echo && echo "Extracted TXDs" && echo && echo
@touch $@
# Clustering them
$(REPACK_DIR)/clustered: $(REPACK_DIR)/extracted ../src/tools/pal-clusters.py
echo "Creating clusters..."
python3 ../src/tools/pal-clusters.py $(REPACK_TEXTURES_DIR) $(REPACK_TEXTURE_CLUSTERS_DIR)
echo && echo && echo "Created texture clusters" && echo && echo
@touch $@
# Palette creation
CLUSTERS := $(shell seq 0 63)
PAL_FILES := $(foreach cluster,$(CLUSTERS),$(REPACK_TEXTURE_CLUSTERS_DIR)/$(cluster).pal)
$(REPACK_TEXTURE_CLUSTERS_DIR)/%.pal: $(REPACK_DIR)/clustered | pvrtex
../vendor/pvrtex/pvrtex $$(ls $(REPACK_TEXTURE_CLUSTERS_DIR)/cluster_$*/*.tga | sed 's/^/-i /') -f PAL4BPP -o $@
$(REPACK_GTA_DIR)/dc-palette: $(REPACK_DIR)/clustered $(PAL_FILES) merge-palettes
./merge-palettes $(REPACK_TEXTURE_CLUSTERS_DIR) $(REPACK_GTA_DIR)/dc-palette
echo && echo && echo "Created cluster palettes" && echo && echo
$(REPACK_DIR)/repacked: $(REPACK_GTA_DIR)/models/gta3.img $(REPACK_GTA_DIR)/models/gta3.dir $(LOOSE_FILES_DC) $(STREAM_ADPCM_DC) $(SFX_DC_RAW) $(SFX_DC_DSC) streamheaderpack $(REPACK_GTA_DIR)/dc-palette
$(REPACK_DIR)/repacked: $(REPACK_GTA_DIR)/models/gta3.img $(REPACK_GTA_DIR)/models/gta3.dir $(LOOSE_FILES_DC) $(STREAM_ADPCM_DC) $(SFX_DC_RAW) $(SFX_DC_DSC) streamheaderpack
mkdir -p $(@D)
# $(REPACK_GTA_DIR) needed as first argument as paths in the game prefix with stream/
./streamheaderpack liberty $(REPACK_GTA_DIR) $(REPACK_STREAM_DEST_DIR)/hdr.bin
cp $(REPACK_GTA_DIR)/dc-palette $(REPACK_GTA_DIR)/dc-palette.pal
@git archive --format zip --output "$(REPACK_GTA_DIR)/DCA3-$(GIT_VERSION).zip" HEAD
@touch $@
@echo && echo && echo "*** Repack Completed Successfully ($(PROJECT_NAME)) ***" && echo && echo
@@ -532,18 +456,18 @@ $(REPACK_IMG_DC_DIR)/%.DFF: $(REPACK_IMG_ORIG_DIR)/%.DFF texconv
./texconv $< $@
# first try the mods img directory. NB, the textures are not resized here, unlike normal .img textures
$(REPACK_IMG_DC_DIR)/%.txd: $(GTA_MOD_IMG_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_IMG_DC_DIR)/%.txd: $(GTA_MOD_IMG_DIR)/%.txd texconv
@mkdir -p $(@D)
./texconv $< $@ 1024 1024 -e $(PVR_ENCODER) -d NONE
$(REPACK_IMG_DC_DIR)/%.TXD: $(GTA_MOD_IMG_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_IMG_DC_DIR)/%.TXD: $(GTA_MOD_IMG_DIR)/%.TXD texconv
@mkdir -p $(@D)
./texconv $< $@ 1024 1024 -e $(PVR_ENCODER) -d NONE
# if not, the extracted img directory
$(REPACK_IMG_DC_DIR)/%.txd: $(REPACK_IMG_ORIG_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_IMG_DC_DIR)/%.txd: $(REPACK_IMG_ORIG_DIR)/%.txd texconv
@mkdir -p $(@D)
./texconv $< $@ $(DEFAULT_RES) $(DEFAULT_RES) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_IMG)
$(REPACK_IMG_DC_DIR)/%.TXD: $(REPACK_IMG_ORIG_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_IMG_DC_DIR)/%.TXD: $(REPACK_IMG_ORIG_DIR)/%.TXD texconv
@mkdir -p $(@D)
./texconv $< $@ $(DEFAULT_RES) $(DEFAULT_RES) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_IMG)
@@ -589,26 +513,26 @@ $(REPACK_GTA_DIR)/%.DFF: $(GTA_DIR)/%.DFF texconv
# first try the mods loose directory
# Note the mods loose directory is not resized, unlike the normal .txd textures
$(REPACK_GTA_DIR)/%.txd: $(GTA_MOD_LOOSE_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_GTA_DIR)/%.txd: $(GTA_MOD_LOOSE_DIR)/%.txd texconv
@mkdir -p $(@D)
./texconv $< $@ 1024 1024 -e $(PVR_ENCODER) -d NONE
$(REPACK_GTA_DIR)/%.TXD: $(GTA_MOD_LOOSE_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_GTA_DIR)/%.TXD: $(GTA_MOD_LOOSE_DIR)/%.TXD texconv
@mkdir -p $(@D)
./texconv $< $@ 1024 1024 -e $(PVR_ENCODER) -d NONE
# then the gamefiles directory
$(REPACK_GTA_DIR)/%.txd: $(GTA_GAMEFILES_LOOSE_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_GTA_DIR)/%.txd: $(GTA_GAMEFILES_LOOSE_DIR)/%.txd texconv
@mkdir -p $(@D)
./texconv $< $@ $(TXD_OPTS_$(notdir $*)) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_TXD)
$(REPACK_GTA_DIR)/%.TXD: $(GTA_GAMEFILES_LOOSE_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_GTA_DIR)/%.TXD: $(GTA_GAMEFILES_LOOSE_DIR)/%.TXD texconv
@mkdir -p $(@D)
./texconv $< $@ $(TXD_OPTS_$(notdir $*)) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_TXD)
# if not, the original files
$(REPACK_GTA_DIR)/%.txd: $(GTA_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_GTA_DIR)/%.txd: $(GTA_DIR)/%.txd texconv
@mkdir -p $(@D)
./texconv $< $@ $(TXD_OPTS_$(notdir $*)) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_TXD)
$(REPACK_GTA_DIR)/%.TXD: $(GTA_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
$(REPACK_GTA_DIR)/%.TXD: $(GTA_DIR)/%.TXD texconv
@mkdir -p $(@D)
./texconv $< $@ $(TXD_OPTS_$(notdir $*)) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_TXD)

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

@@ -1,46 +1,6 @@
# models/coll/peds.col # not actually used
MISC_TXD = \
models/fonts.txd \
models/frontend.txd \
models/generic.txd \
models/hud.txd \
models/menu.txd \
models/MISC.TXD \
models/particle.txd \
txd/LOADSC0.TXD \
txd/LOADSC1.TXD \
txd/LOADSC10.TXD \
txd/LOADSC11.TXD \
txd/LOADSC12.TXD \
txd/LOADSC13.TXD \
txd/LOADSC14.TXD \
txd/LOADSC15.TXD \
txd/LOADSC16.TXD \
txd/LOADSC17.TXD \
txd/LOADSC18.TXD \
txd/LOADSC19.TXD \
txd/LOADSC2.TXD \
txd/LOADSC20.TXD \
txd/LOADSC21.TXD \
txd/LOADSC22.TXD \
txd/LOADSC23.TXD \
txd/LOADSC24.TXD \
txd/LOADSC25.TXD \
txd/LOADSC3.TXD \
txd/LOADSC4.TXD \
txd/LOADSC5.TXD \
txd/LOADSC6.TXD \
txd/LOADSC7.TXD \
txd/LOADSC8.TXD \
txd/LOADSC9.TXD \
txd/mainsc1.txd \
txd/mainsc2.txd \
txd/NEWS.TXD \
txd/SPLASH1.TXD \
txd/SPLASH2.TXD \
txd/SPLASH3.TXD
MISC_FILES = $(MISC_TXD) \
MISC_FILES = \
anim/cuts.dir \
anim/cuts.img \
anim/gta3.ini \
@@ -176,4 +136,44 @@ MISC_FILES = $(MISC_TXD) \
TEXT/italian.gxt \
TEXT/spanish.gxt \
\
models/fonts.txd \
models/frontend.txd \
models/generic.txd \
models/hud.txd \
models/menu.txd \
models/MISC.TXD \
models/particle.txd \
txd/LOADSC0.TXD \
txd/LOADSC1.TXD \
txd/LOADSC10.TXD \
txd/LOADSC11.TXD \
txd/LOADSC12.TXD \
txd/LOADSC13.TXD \
txd/LOADSC14.TXD \
txd/LOADSC15.TXD \
txd/LOADSC16.TXD \
txd/LOADSC17.TXD \
txd/LOADSC18.TXD \
txd/LOADSC19.TXD \
txd/LOADSC2.TXD \
txd/LOADSC20.TXD \
txd/LOADSC21.TXD \
txd/LOADSC22.TXD \
txd/LOADSC23.TXD \
txd/LOADSC24.TXD \
txd/LOADSC25.TXD \
txd/LOADSC3.TXD \
txd/LOADSC4.TXD \
txd/LOADSC5.TXD \
txd/LOADSC6.TXD \
txd/LOADSC7.TXD \
txd/LOADSC8.TXD \
txd/LOADSC9.TXD \
txd/mainsc1.txd \
txd/mainsc2.txd \
txd/NEWS.TXD \
txd/SPLASH1.TXD \
txd/SPLASH2.TXD \
txd/SPLASH3.TXD \
\
audio/sfx.SDT

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

@@ -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;
}
@@ -363,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) {
@@ -389,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) {
@@ -419,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) {
@@ -439,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;
@@ -447,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;
}
@@ -487,6 +506,7 @@ cSampleManager::Initialise(void)
void
cSampleManager::Terminate(void)
{
CdStreamDiscardAudioRead(fdPedSfx);
fs_close(fdPedSfx);
}
@@ -525,6 +545,7 @@ void
cSampleManager::SetMusicMasterVolume(uint8 nVolume)
{
m_nMusicVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -538,6 +559,7 @@ void
cSampleManager::SetMusicFadeVolume(uint8 nVolume)
{
m_nMusicFadeVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -737,9 +759,9 @@ 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
@@ -1027,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));
@@ -1050,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);
@@ -1085,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
@@ -1208,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) {

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

@@ -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

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

@@ -692,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

@@ -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

@@ -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

@@ -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;
}
@@ -370,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) {
@@ -396,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) {
@@ -426,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) {
@@ -446,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;
@@ -454,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;
}
@@ -494,6 +511,7 @@ cSampleManager::Initialise(void)
void
cSampleManager::Terminate(void)
{
CdStreamDiscardAudioRead(fdPedSfx);
fs_close(fdPedSfx);
}
@@ -520,7 +538,6 @@ cSampleManager::UpdateEffectsVolume(void)
}
}
void
cSampleManager::SetEffectsMasterVolume(uint8 nVolume)
{
@@ -532,6 +549,7 @@ void
cSampleManager::SetMusicMasterVolume(uint8 nVolume)
{
m_nMusicVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -551,6 +569,7 @@ void
cSampleManager::SetMusicFadeVolume(uint8 nVolume)
{
m_nMusicFadeVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -696,8 +715,8 @@ 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);
@@ -793,8 +812,8 @@ 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
@@ -1098,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));
@@ -1130,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);
@@ -1165,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
@@ -1292,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) {

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

@@ -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

@@ -718,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

@@ -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

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

View File

@@ -1,69 +0,0 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstdint>
int main(int argc, char* argv[]) {
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " <input_root_folder> <output_file>" << std::endl;
return 1;
}
std::string inputFolder = argv[1];
std::string outputFileName = argv[2];
// Open the output file for writing in binary mode.
std::ofstream outFile(outputFileName, std::ios::binary);
if (!outFile) {
std::cerr << "Error: Cannot open output file " << outputFileName << std::endl;
return 1;
}
// Process each file from 0.pal to 63.pal.
for (int i = 0; i < 64; ++i) {
std::string filePath = inputFolder + "/" + std::to_string(i) + ".pal";
std::ifstream inFile(filePath, std::ios::binary);
if (!inFile) {
std::cerr << "Error: Cannot open input file " << filePath << std::endl;
return 1;
}
// Read header (first 4 bytes). They should equal "DPAL".
char header[4];
inFile.read(header, 4);
if (inFile.gcount() != 4 || std::string(header, 4) != "DPAL") {
std::cerr << "Error: File " << filePath << " has an invalid header." << std::endl;
return 1;
}
// Read the next 4 bytes (number of palette entries).
uint32_t numEntries = 0;
inFile.read(reinterpret_cast<char*>(&numEntries), sizeof(numEntries));
if (inFile.gcount() != sizeof(numEntries)) {
std::cerr << "Error: Could not read palette entry count from " << filePath << std::endl;
return 1;
}
if (numEntries != 16) {
std::cerr << "Error: File " << filePath << " has " << numEntries
<< " entries, expected 16." << std::endl;
return 1;
}
// Read the remaining bytes (the palette values).
std::vector<char> paletteData((std::istreambuf_iterator<char>(inFile)),
std::istreambuf_iterator<char>());
inFile.close();
// Write palette data to the output file.
outFile.write(paletteData.data(), paletteData.size());
if (!outFile) {
std::cerr << "Error: Writing to output file failed." << std::endl;
return 1;
}
}
outFile.close();
std::cout << "Successfully combined 64 .pal files into " << outputFileName << std::endl;
return 0;
}

View File

@@ -1,128 +0,0 @@
import os
import shutil
import argparse
import numpy as np
from PIL import Image
from sklearn.cluster import KMeans
def compute_mse(original, quantized):
"""
Compute Mean Squared Error between two images (numpy arrays).
"""
if original.shape != quantized.shape:
raise ValueError("Images must have the same dimensions")
mse = np.mean((original - quantized) ** 2)
return mse
def extract_palette_feature(quantized_image, num_colors=16):
"""
Extract a flattened feature vector from the quantized image palette.
Uses the getcolors() method to get (count, color) tuples.
If the color is an integer (palette index), it converts it to an RGB tuple.
Sorts the colors by brightness (sum of RGB).
Pads with zeros if fewer than num_colors colors are present.
"""
colors = quantized_image.getcolors(maxcolors=256)
if colors is None:
raise ValueError("Too many colors in quantized image")
raw_palette = quantized_image.getpalette()
color_list = []
for count, col in colors:
# Convert palette index to RGB if needed.
if isinstance(col, int):
rgb = tuple(raw_palette[col*3: col*3+3])
else:
rgb = col
color_list.append(rgb)
color_list.sort(key=lambda c: sum(c))
if len(color_list) < num_colors:
pad_length = num_colors - len(color_list)
color_list.extend([(0, 0, 0)] * pad_length)
elif len(color_list) > num_colors:
color_list = color_list[:num_colors]
feature = np.array(color_list).flatten()
return feature
def process_textures(input_dir, output_dir, error_threshold, num_palette_groups=64, palette_colors=16):
accepted_features = []
accepted_files = []
non_paletteable_files = []
for filename in os.listdir(input_dir):
if filename.lower().endswith('.tga'):
filepath = os.path.join(input_dir, filename)
try:
original = Image.open(filepath).convert("RGB")
# Quantize image to a palette of palette_colors colors.
quantized = original.quantize(colors=palette_colors, method=Image.FASTOCTREE, dither=Image.NONE)
quantized_rgb = quantized.convert("RGB")
original_arr = np.array(original, dtype=np.float32)
quantized_arr = np.array(quantized_rgb, dtype=np.float32)
mse = compute_mse(original_arr, quantized_arr)
if mse <= error_threshold:
feature = extract_palette_feature(quantized, num_colors=palette_colors)
accepted_features.append(feature)
accepted_files.append(filepath)
# print(f"File {filename} MSE={mse:.2f} -> paletteable")
else:
non_paletteable_files.append(filepath)
# print(f"File {filename} MSE={mse:.2f} -> non-paletteable")
except Exception as e:
print(f"Error processing {filename}: {e}")
print(f"Total textures processed: {len(accepted_files) + len(non_paletteable_files)}")
print(f"Paletteable textures: {len(accepted_files)}")
print(f"Non-paletteable textures: {len(non_paletteable_files)}")
if accepted_features:
features_array = np.array(accepted_features)
kmeans = KMeans(n_clusters=num_palette_groups, random_state=42)
cluster_labels = kmeans.fit_predict(features_array)
for i in range(num_palette_groups):
cluster_dir = os.path.join(output_dir, f"cluster_{i}")
os.makedirs(cluster_dir, exist_ok=True)
for filepath, label in zip(accepted_files, cluster_labels):
dest_dir = os.path.join(output_dir, f"cluster_{label}")
shutil.copy(filepath, dest_dir)
cluster_filepath = filepath + ".cluster"
with open(cluster_filepath, "w") as cluster_file:
cluster_file.write(str(label))
nonpal_dir = os.path.join(output_dir, "cluster_64")
os.makedirs(nonpal_dir, exist_ok=True)
for filepath in non_paletteable_files:
shutil.copy(filepath, nonpal_dir)
cluster_filepath = filepath + ".cluster"
with open(cluster_filepath, "w") as cluster_file:
cluster_file.write("64")
print("Grouping complete.")
def main():
parser = argparse.ArgumentParser(description="Group .tga textures into palette clusters and a non-paletteable group.")
parser.add_argument("input_dir", type=str, help="Path to folder containing .tga textures")
parser.add_argument("output_dir", type=str, help="Path to output folder for grouped textures")
parser.add_argument("--threshold", type=float, default=500.0,
help="Error threshold for palette quality (default: 500.0)")
parser.add_argument("--palette_colors", type=int, default=16,
help="Number of colors for palette quantization (default: 16)")
parser.add_argument("--num_palette_groups", type=int, default=64,
help="Number of palette groups to form (default: 64)")
args = parser.parse_args()
os.makedirs(args.output_dir, exist_ok=True)
process_textures(args.input_dir, args.output_dir, args.threshold, args.num_palette_groups, args.palette_colors)
if __name__ == "__main__":
main()

View File

@@ -67,7 +67,6 @@ namespace rw::dc {
extern int32 maxRasterHeight;
extern int32 downsampleMode;
extern int32 pvrEncoder;
extern const char* dstFile;
}
RwTexDictionary *LoadTxd(RwStream *stream);
@@ -308,8 +307,6 @@ int main(int argc, const char** argv) {
rw::dc::pvrEncoder = PVRTOOL;
} else if (strcmp(param, "pvrtex") == 0 || strcmp(param, "PVRTEX") == 0) {
rw::dc::pvrEncoder = PVRTEX;
} else if (strcmp(param, "extract") == 0 || strcmp(param, "EXTRACT") == 0) {
rw::dc::pvrEncoder = EXTRACT;
}
}
}
@@ -347,8 +344,6 @@ int main(int argc, const char** argv) {
assert(RwEngineStart());
currentFile = argv[1];
rw::dc::dstFile = argv[2];
if (strstr(argv[1], ".txd") || strstr(argv[1], ".TXD")) {
auto stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, argv[1]);
assert(stream && "failed to open input");
@@ -383,14 +378,12 @@ int main(int argc, const char** argv) {
}
}
if (rw::dc::pvrEncoder != EXTRACT) {
auto streamOut = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, argv[2]);
assert(streamOut && "failed to open output");
StoreTxd(texDict, streamOut);
RwStreamClose(streamOut, nil);
}
auto streamOut = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, argv[2]);
assert(streamOut && "failed to open output");
StoreTxd(texDict, streamOut);
RwStreamClose(streamOut, nil);
} else if (strstr(argv[1], ".dff") || strstr(argv[1], ".DFF")) {
rw::Texture::setLoadTextures(false);
rw::Texture::setCreateDummies(true);

View File

@@ -10,7 +10,6 @@
#endif
#if defined(DC_TEXCONV)
#include <fcntl.h>
#include "tri_stripper.h"
#include <sha256.h>
extern const char* currentFile;
@@ -576,7 +575,7 @@ size_t vertexBufferFree() {
bool vertexOverflown() {
return PVR_GET(PVR_TA_VERTBUF_POS) >= PVR_GET(PVR_TA_VERTBUF_END) ||
PVR_GET(PVR_TA_OPB_POS)*4 >= PVR_GET(PVR_TA_OPB_END);
(PVR_GET(PVR_TA_OPB_POS)*4 >= PVR_GET(PVR_TA_OPB_END) && PVR_GET(PVR_TA_OPB_POS) != PVR_GET(PVR_TA_OPB_INIT));
}
constexpr size_t freeVertexTarget_Step_Up = 32 * 1024;
@@ -1037,7 +1036,7 @@ public:
// Templated constructor to accept any callable object.
template <typename F>
move_only_function(F f)
move_only_function(F&& f)
: callable_(new model<F>(std::move(f))) {}
// Move constructor.
@@ -1081,7 +1080,7 @@ private:
template <typename F>
struct model : concept_t {
F f;
explicit model(F f) : f(std::move(f)) {}
explicit model(F&& f) : f(std::move(f)) {}
R invoke(Args&&... args) override {
return f(std::forward<Args>(args)...);
}
@@ -1094,8 +1093,27 @@ chunked_vector<move_only_function<void()>> opCallbacks;
chunked_vector<move_only_function<void()>> blendCallbacks;
chunked_vector<move_only_function<void()>> ptCallbacks;
static const unsigned short VIDEO_MODES = 2;
static unsigned short VIDEO_MODE = 0;
static rw::VideoMode videoModes[VIDEO_MODES] = {
{ 640, 480, 16, VIDEOMODEEXCLUSIVE },
{ 640, 480, 24, VIDEOMODEEXCLUSIVE },
};
static pvr_init_params_t pvr_params = {
.opb_sizes = {
PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_8, PVR_BINSIZE_0,
PVR_BINSIZE_8
},
.autosort_disabled = true
};
void dcMotionBlur_v1(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
// not supported on 24 bpp
if (videoModes[VIDEO_MODE].depth == 24) {
return;
}
uint32_t col = (a << 24) | (r << 16) | (g << 8) | b;
blendCallbacks.emplace_back([=]() {
@@ -1205,6 +1223,11 @@ void dcMotionBlur_v1(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
}
void dcMotionBlur_v3(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
// not supported on 24 bpp
if (videoModes[VIDEO_MODE].depth == 24) {
return;
}
uint32_t alpha = a;
uint32_t col = (alpha * r / 255 << 16) | (alpha * g / 255 << 8) | alpha * b / 255;
uint32_t mask_col = ((255 - a) << 16) | ((255 - a) << 8) | (255 - a);
@@ -4601,7 +4624,6 @@ int32 maxRasterWidth = 64;
int32 maxRasterHeight = 64;
int32 downsampleMode = NONE;
int32 pvrEncoder = PVRTEX;
const char* dstFile;
#endif
bool32
@@ -4774,11 +4796,6 @@ rasterFromImage(Raster* raster, Image* image)
assert(false && "Unhandled texture format");
}
hash_sha256 img_hash;
img_hash.sha256_init();
img_hash.sha256_update((const uint8_t*)imageData.data(), imageData.size() * sizeof(imageData[0]));
sha256_type img_hash_result = img_hash.sha256_final();
if (raster->width != image->width || raster->height != image->height) {
printf("Downsample: %ix%i -> %ix%i\n", image->width, image->height, raster->width, raster->height);
imageData = downscaleImage(imageData, image->width, image->height, raster->width, raster->height);
@@ -4803,99 +4820,50 @@ rasterFromImage(Raster* raster, Image* image)
fprintf(stderr, "Failed to write TGA file: %s\n", filename_tga);
return false;
}
if (pvrEncoder != EXTRACT) {
char encodeCommand[512];
std::stringstream clusterfile;
clusterfile << "repack-data/textures/" << std::hex;
for (int i = 0; i < 32; i++) {
clusterfile << std::setfill('0') << std::setw(2) << (int)img_hash_result[i];
}
clusterfile << ".tga.cluster";
char encodeCommand[512];
int cluster = -1;
FILE* fclust = fopen(clusterfile.str().c_str(), "r");
if (!fclust) {
fprintf(stderr, "cluster: %s\n", clusterfile.str().c_str());
}
assert(fclust);
// Now call PVR Compression
switch(pvrEncoder) {
#if defined(_WIN32) || defined(_WIN64)
case PVRTEX:
snprintf(encodeCommand, sizeof(encodeCommand),
"..\\vendor\\pvrtex\\pvrtex.exe -i %s -o %s -c small -d", filename_tga, filename_pvr);
break;
case PVRTOOL:
snprintf(encodeCommand, sizeof(encodeCommand),
"pvrtool.exe %s -OF pvr -TW -CF SMART -VQ -VQDITHER 1 -o %s",
filename_tga, filename_pvr);
break;
#else
case PVRTEX:
snprintf(encodeCommand, sizeof(encodeCommand),
"../vendor/pvrtex/pvrtex -i %s -o %s -c small -d", filename_tga, filename_pvr);
break;
case PVRTOOL:
snprintf(encodeCommand, sizeof(encodeCommand),
"./pvrtool %s -OF pvr -TW -CF SMART -VQ -VQDITHER 1 -o %s",
filename_tga, filename_pvr);
break;
#endif
}
fscanf(fclust, "%d", &cluster);
fclose(fclust);
int retCode = system(encodeCommand);
assert(cluster >= 0 && cluster <= 64);
// Read PVR File
assert(raster->width && raster->height && !natras->raster->texaddr);
loadPVR(filename_pvr, raster, natras->raster, PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE);
// Now call PVR Compression
switch(pvrEncoder) {
#if defined(_WIN32) || defined(_WIN64)
case PVRTEX:
snprintf(encodeCommand, sizeof(encodeCommand),
"..\\vendor\\pvrtex\\pvrtex.exe -i %s -o %s -c small -d", filename_tga, filename_pvr);
break;
case PVRTOOL:
snprintf(encodeCommand, sizeof(encodeCommand),
"pvrtool.exe %s -OF pvr -TW -CF SMART -VQ -VQDITHER 1 -o %s",
filename_tga, filename_pvr);
break;
#else
case PVRTEX:
if (cluster == 64)
snprintf(encodeCommand, sizeof(encodeCommand),"../vendor/pvrtex/pvrtex -i %s -o %s -c small -d", filename_tga, filename_pvr);
else
snprintf(encodeCommand, sizeof(encodeCommand),"../vendor/pvrtex/pvrtex -i %s -o %s -c small -d -f PAL4BPP -q repack-data/texture-clusters/%d.pal", filename_tga, filename_pvr, cluster);
break;
case PVRTOOL:
snprintf(encodeCommand, sizeof(encodeCommand),
"./pvrtool %s -OF pvr -TW -CF SMART -VQ -VQDITHER 1 -o %s",
filename_tga, filename_pvr);
break;
#endif
case EXTRACT:
break;
}
remove(filename_tga);
remove(filename_pvr);
hash_sha256 hash;
hash.sha256_init();
hash.sha256_update((const uint8_t*)natras->raster->texaddr, natras->raster->texsize);
sha256_type hash_result = hash.sha256_final();
int retCode = system(encodeCommand);
// Read PVR File
assert(raster->width && raster->height && !natras->raster->texaddr);
loadPVR(filename_pvr, raster, natras->raster, PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE);
remove(filename_tga);
remove(filename_pvr);
if (cluster != 64) {
natras->raster->pvr_flags |= PVR_TXRFMT_4BPP_PAL(cluster);
}
hash_sha256 hash;
hash.sha256_init();
hash.sha256_update((const uint8_t*)natras->raster->texaddr, natras->raster->texsize);
sha256_type hash_result = hash.sha256_final();
natras->raster->pvr_id = hash_result[0] | (hash_result[1] << 8) | (hash_result[2] << 16) | (hash_result[3] << 24);
} else {
std::stringstream touchfile;
touchfile << dstFile << ".contents/" << std::hex;
std::stringstream texture;
texture << "repack-data/textures/" << std::hex;
for (int i = 0; i < 32; i++) {
touchfile << std::setfill('0') << std::setw(2) << (int)img_hash_result[i];
texture << std::setfill('0') << std::setw(2) << (int)img_hash_result[i];
}
texture << ".tga";
int fd = open(touchfile.str().c_str(), O_CREAT | O_TRUNC, 0666);
assert(fd != -1);
close(fd);
assert(rename(filename_tga, texture.str().c_str()) == 0);
}
natras->raster->pvr_id = hash_result[0] | (hash_result[1] << 8) | (hash_result[2] << 16) | (hash_result[3] << 24);
if(truecolimg)
@@ -5033,14 +5001,6 @@ rasterToImage(Raster*)
return nil;
}
static pvr_init_params_t pvr_params = {
.opb_sizes = {
PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_8, PVR_BINSIZE_0,
PVR_BINSIZE_8
},
.autosort_disabled = true
};
int
deviceSystem(DeviceReq req, void *arg0, int32 n)
{
@@ -5070,10 +5030,10 @@ deviceSystem(DeviceReq req, void *arg0, int32 n)
case DEVICEGETVIDEOMODEINFO:{
auto rwmode = (VideoMode*)arg0;
rwmode->width = 640;
rwmode->height = 480;
rwmode->depth = 16;
rwmode->flags = VIDEOMODEEXCLUSIVE;
rwmode->width = videoModes[n].width;
rwmode->height = videoModes[n].height;
rwmode->depth = videoModes[n].depth;
rwmode->flags = videoModes[n].flags;
return 1;
}
case DEVICEGETMAXMULTISAMPLINGLEVELS:
@@ -5084,22 +5044,19 @@ deviceSystem(DeviceReq req, void *arg0, int32 n)
if (n == 1) {
VIDEO_MODE_SCALE_X = 1;
pvr_params.fsaa_enabled = 0;
pvr_params.vertex_buf_size = (1024 + 1024) * 1024;
pvr_params.opb_overflow_count = 7; // 268800 bytes
} else {
VIDEO_MODE_SCALE_X = 2;
pvr_params.fsaa_enabled = 1;
pvr_params.vertex_buf_size = (1024 + 768) * 1024;
pvr_params.opb_overflow_count = 4; // 307200 bytes
}
return 1;
case DEVICESETSUBSYSTEM:
return 1;
case DEVICEGETNUMVIDEOMODES:
return 1;
return VIDEO_MODES;
case DEVICEGETCURRENTVIDEOMODE:
return 0;
return VIDEO_MODE;
case DEVICESETVIDEOMODE:
VIDEO_MODE = n;
return 1;
default:
assert(0 && "not implemented");
@@ -5180,32 +5137,31 @@ driverOpen(void *o, int32, int32)
#endif
#if !defined(DC_TEXCONV)
dbglog(DBG_CRITICAL, "atomicContexts: %d per %d allocation\n", decltype(atomicContexts)::chunk::item_count, decltype(atomicContexts)::chunk_size);
dbglog(DBG_CRITICAL, "skinContexts: %d per %d allocation\n", decltype(skinContexts)::chunk::item_count, decltype(atomicContexts)::chunk_size);
dbglog(DBG_CRITICAL, "matfxContexts: %d per %d allocation\n", decltype(matfxContexts)::chunk::item_count, decltype(atomicContexts)::chunk_size);
dbglog(DBG_CRITICAL, "opCallbacks: %d per %d allocation\n", decltype(opCallbacks)::chunk::item_count, decltype(atomicContexts)::chunk_size);
dbglog(DBG_CRITICAL, "blendCallbacks: %d per %d allocation\n", decltype(blendCallbacks)::chunk::item_count, decltype(atomicContexts)::chunk_size);
dbglog(DBG_CRITICAL, "ptCallbacks: %d per %d allocation\n", decltype(ptCallbacks)::chunk::item_count, decltype(atomicContexts)::chunk_size);
#endif
pvr_init(&pvr_params);
#if !defined(DC_TEXCONV)
uint32_t palette[1024];
FILE* fpal = fopen("dc-palette.pal", "rb");
assert(fpal);
fread(palette, 1, 1024 * 4, fpal);
fclose(fpal);
// write to pal regs
PVR_SET(0x108, 0x3); // ARGB8888 pals
for (int i = 0; i < 1024; i++) {
PVR_SET(0x1000 + i*4, palette[i]);
if (pvr_params.fsaa_enabled) {
pvr_params.vertex_buf_size = (1024 + 768) * 1024;
pvr_params.opb_overflow_count = 4; // 307200 bytes
} else {
pvr_params.vertex_buf_size = (1024 + 1024) * 1024;
pvr_params.opb_overflow_count = 7; // 268800 bytes
}
if (videoModes[VIDEO_MODE].depth == 24) {
pvr_params.vertex_buf_size -= 128 * 1024;
pvr_params.opb_overflow_count -= pvr_params.fsaa_enabled ? 1 : 2;
}
#if !defined(DC_SIM)
vid_set_mode(DM_640x480, videoModes[VIDEO_MODE].depth == 24 ? PM_RGB888P : PM_RGB565);
#endif
pvr_init(&pvr_params);
fake_tex = pvr_mem_malloc(sizeof(fake_tex_data));
@@ -5330,9 +5286,9 @@ readNativeTexture(Stream *stream)
#ifdef DC_SH4
uint8 *src = stream->mmap(pvr_size);
// assert((pvr_size & 31) == 0);
assert((pvr_size & 31) == 0);
if (src) {
if (((uintptr_t)src & 31) || pvr_size & 31) {
if (((uintptr_t)src & 31)) {
dcache_pref_block(src);
if ((uintptr_t)src & 3) {

View File

@@ -21,8 +21,7 @@ enum downsampleModes {
enum pvrEncoders {
PVRTOOL,
PVRTEX,
EXTRACT
PVRTEX
};
// TGA Header Struct
@@ -142,10 +141,6 @@ void loadPVR(char *fname, rw::Raster* raster, auto* natras, auto flags) {
natras->pvr_flags |= PVR_TXRFMT_YUV422;
rasterFmt = rw::Raster::C565; // this is a bit of a hack
break;
case 0x5: // PAL4
natras->pvr_flags |= PVR_TXRFMT_PAL4BPP;
rasterFmt = raster->format & 0x0F00; // perserve for blending reasons
break;
default:
assert(false && "Invalid texture format");
break;
@@ -158,11 +153,11 @@ void loadPVR(char *fname, rw::Raster* raster, auto* natras, auto flags) {
natras->texaddr = alloc_malloc(natras, natras->texsize);
fread(natras->texaddr, 1, natras->texsize, tex); /* Read in the PVR texture data */
texconvf("PVR TEXTURE READ: %ix%i, %i, %i\n", HDR.nWidth, HDR.nHeight, natras->texoffs, natras->texsize);
// if (natras->texsize >= 256) {
// assert((natras->texsize & 31) == 0);
// } else {
// assert((natras->texsize & 31) == 0);
// }
if (natras->texsize >= 256) {
assert((natras->texsize & 255) == 0);
} else {
assert((natras->texsize & 31) == 0);
}
fclose(tex);
}

View File

@@ -53,8 +53,7 @@ void fPvrWrite(const PvrTexEncoder *pte, const char *outfname) {
}
if (pteIsPalettized(pte))
idxcnt/= 4;
// ErrorExit(".PVR format does not support compressed palettized textures\n");
ErrorExit(".PVR format does not support compressed palettized textures\n");
// JP - Rectangle VQ certainly does work on real hardware
//if (pte->w != pte->h)
// ErrorExit(".PVR format does not support non-square compressed textures\n");

50
vendor/pvrtex/main.c vendored
View File

@@ -12,7 +12,7 @@
#include "file_pvr.h"
#include "file_tex.h"
int log_level = LOG_DEBUG;
int log_level = LOG_PROGRESS;
void pteLogLocV(unsigned level, const char *file, unsigned line, const char *fmt, va_list args) {
static const char * logtypes[] = {
[LOG_ALL] = "ALL",
@@ -163,11 +163,10 @@ int main(int argc, char **argv) {
{"mip-resize", 'R', OPTPARSE_OPTIONAL},
{"stride", 's', OPTPARSE_NONE},
{"edge", 'e', OPTPARSE_REQUIRED},
{"pallette", 'q', OPTPARSE_REQUIRED},
{0}
};
#define MAX_FNAMES 1024
#define MAX_FNAMES 11
const char *fnames[MAX_FNAMES];
unsigned fname_cnt = 0;
const char *outname = "";
@@ -299,23 +298,6 @@ int main(int argc, char **argv) {
ErrorExit("invalid max palette size parameter (should be [1, 16] for 4bpp, or [1, 256] for 8bpp)\n");
}
break;
case 'q': {
pxlARGB8888 pal[16];
FILE* f = fopen(options.optarg, "rb");
assert(f);
assert(fseek(f, 8, SEEK_SET) == 0);
assert(fread(pal, 1, 4 * 16, f) == 4 * 16);
fclose(f);
pte.palette = malloc(16 * 4);
pte.palette_size = 16;
assert(pte.palette);
for (int i = 0; i < 16; i++) {
pte.palette[i] = pxlConvertARGB8888toABGR8888(pal[i]);
}
}
break;
default:
ErrorExit("%s\n", options.errmsg);
}
@@ -408,34 +390,6 @@ int main(int argc, char **argv) {
pte.edge_method = STBIR_EDGE_CLAMP;
}
if (strcasecmp(extension, ".pal") == 0) {
//Generate palette
if (pte.pixel_format == PTE_PALETTE_4B || pte.pixel_format == PTE_PALETTE_8B) {
if (pte.pixel_format == PTE_PALETTE_8B) {
if (pte.palette_size == 0) {
pte.palette_size = 256;
} else if (pte.palette_size > 256) {
ErrorExit("palette size must be 256 or less for 8bpp textures\n");
}
} else if (pte.pixel_format == PTE_PALETTE_4B) {
if (pte.palette_size == 0) {
pte.palette_size = 16;
} else if (pte.palette_size > 16) {
ErrorExit("palette size must be 16 or less for 4bpp textures\n");
}
}
pteLog(LOG_PROGRESS, "Generating palette...\n");
} else {
assert(0 && ".pal file but no pal format");
}
pteGenerateGlobalPalette(&pte);
fTexWritePalette(&pte, outname);
// pteFree(&pte); // its okay, this will leak a bit
return 0;
}
pteEncodeTexture(&pte);
//Make preview

View File

@@ -446,15 +446,6 @@ static inline pxlRGBA32 pxlConvertABGR8888toRGBA32(pxlABGR8888 color) {
ret.a = color.a;
return ret;
}
static inline pxlABGR8888 pxlConvertARGB8888toABGR8888(pxlARGB8888 color) {
pxlABGR8888 ret;
ret.r = color.r;
ret.g = color.g;
ret.b = color.b;
ret.a = color.a;
return ret;
}
static inline pxlARGB8888 pxlConvertABGR8888toARGB8888(pxlABGR8888 color) {
pxlARGB8888 ret;
ret.r = color.r;

View File

@@ -11,7 +11,7 @@ extern "C" {
#define PVR_MAX_TEXTURE_WIDTH 1024
#define PVR_MAX_TEXTURE_HEIGHT 1024
#define PVR_MAX_MIPMAPS (1024)
#define PVR_MAX_MIPMAPS (11)
#define CHANNEL_CNT_ARGB 4
#define VECTOR_W 2

View File

@@ -85,10 +85,10 @@ void pteLoadFromFiles(PvrTexEncoder *pte, const char **fnames, unsigned filecnt)
"When using custom mipmaps, the size of all levels must be a power of two"
" (resize is not supported). %s has a size of %ux%u\n", fnames[i],
img->w, img->h);
// ErrorExitOn(img->w != img->h,
// "When using custom mipmaps, all levels must be square"
// " (resize is not supported). %s has a size of %ux%u\n", fnames[i],
// img->w, img->h);
ErrorExitOn(img->w != img->h,
"When using custom mipmaps, all levels must be square"
" (resize is not supported). %s has a size of %ux%u\n", fnames[i],
img->w, img->h);
}
maxw = MAX(maxw, img->w);
@@ -288,38 +288,7 @@ void pteDitherRaws(PvrTexEncoder *pte, float dither_amt) {
}
void pteGenerateGlobalPalette(PvrTexEncoder *pte) {
assert(pte);
assert(pte->palette == NULL);
assert(pte->palette_size > 0);
assert(pte->palette_size <= 256);
VQCompressor vqc;
vqcInit(&vqc, VQC_UINT8, 4, 1, pte->palette_size, pte->auto_small_vq);
vqcSetRGBAGamma(&vqc, pte->rgb_gamma, pte->alpha_gamma);
//Add mipmaps to compressor input
for (int i = 0; i < pte->src_img_cnt; i++) {
uint32_t pixelcnt = pte->src_imgs[i].w * pte->src_imgs[i].h;
vqcAddPoints(&vqc, pte->src_imgs[i].pixels, pixelcnt);
}
//Do compression and save resulting palette
vqcResults result = vqcCompress(&vqc, 8);
assert(result.codebook);
pte->palette = result.codebook;
free(result.indices);
//~ for(unsigned i = 0; i < 256; i++) {
//~ printf("(%i, %i, %i) ", pte->palette[i].r, pte->palette[i].g, pte->palette[i].b, pte->palette[i].a);
//~ }
}
void pteGeneratePalette(PvrTexEncoder *pte) {
if (pte->palette) {
// already has palette preloaded
return;
}
assert(pte);
assert(pte->mip_cnt > 0);
assert(pte->mip_cnt <= PVR_MAX_MIPMAPS);

View File

@@ -202,7 +202,6 @@ int pteSetSize(PvrTexEncoder *pte);
void pteSetCompressed(PvrTexEncoder *pte, int codebook_size);
void pteGeneratePreviews(PvrTexEncoder *pte);
void pteAutoSelectPixelFormat(PvrTexEncoder *pte);
void pteGenerateGlobalPalette(PvrTexEncoder *pte);
///////////
void ErrorExitOn(int cond, const char *fmt, ...);