Compare commits

..

12 Commits

Author SHA1 Message Date
Stefanos Kornilios Mitsis Poiitidis
5d0d0073ac WIP on palette with clusters for all textures 2025-03-24 20:51:23 +02:00
Stefanos Kornilios Mitsis Poiitidis
ab0e84bd11 relax overzealous assert in setCurrentAnim 2025-03-24 19:53:28 +02:00
Stefanos Kornilios Mitsis Poiitidis
9b1cd5119a pack for less waste 2025-03-23 09:33:31 +02:00
Stefanos Kornilios Mitsis Poiitidis
39ee8c1f8d rwdc: Switch to context pointers instead of context offsets 2025-03-23 09:24:44 +02:00
Stefanos Kornilios Mitsis Poiitidis
7341715d1b CutsceneHead: Don't leak RpHAnimAnimations 2025-03-23 09:03:25 +02:00
Stefanos Kornilios Mitsis Poiitidis
bb72d48160 ColModel / Triangle planes: more fixes for miami and liberty 2025-03-23 08:23:35 +02:00
Stefanos Kornilios Mitsis Poiitidis
d4a315d560 collision fixes: fix miami linked list corruption, liberty replica 2025-03-23 07:39:22 +02:00
Stefanos Kornilios Mitsis Poiitidis
ed8418b301 fix memleaks and clang 2025-03-23 06:28:18 +02:00
Stefanos Kornilios Mitsis Poiitidis
71f27ffdbe im2d: strip -> fan, rwdc micro wins for memory 2025-03-23 03:15:30 +02:00
Stefanos Kornilios Mitsis Poiitidis
52e30bfcfc Introduce chunked_vector, it has some more overhead than needed but lets see if it helps 2025-03-22 22:50:11 +02:00
Stefanos Kornilios Mitsis Poiitidis
ea5698dfe6 move save/load compression to allocate with re3StreamingAlloc, assert to make sure allocation worked 2025-03-22 18:13:27 +02:00
Stefanos Kornilios Mitsis Poiitidis
6b4432fde9 Introduce re3StreamingAlloc that tries to despawn if alloc fails, use it for allocs during loading 2025-03-22 12:39:25 +02:00
59 changed files with 1308 additions and 2172 deletions

1
.gitignore vendored
View File

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

View File

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

View File

@@ -15,16 +15,16 @@ IS_MAC := $(shell uname -s | grep -i "darwin" > /dev/null && echo "yes" || echo
MOD_NAME?=
GTA_DIR?=../../liberty
GTA_DIR?=../../gta3
GTA_GAMEFILES_LOOSE_DIR?=../gamefiles/liberty
GTA_MOD_DIR?=../../liberty_mod$(MOD_NAME)
GTA_MOD_DIR?=../../gta3_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)/liberty
REPACK_GTA_DIR?=$(REPACK_DIR)/gta3
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,6 +33,9 @@ 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 :=
@@ -183,14 +186,6 @@ $(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
@@ -206,20 +201,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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTA3SF8.b
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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
rm -f $(PROJECT_NAME).ds.iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp $(TARGET).bin $(REPACK_GTA_DIR)/1ST_READ.BIN
@@ -230,7 +225,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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
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)
@@ -249,15 +244,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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTA3SF8.b
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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTA3SF8.b
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
@@ -312,16 +307,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 = 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_fonts = 512 512
TXD_OPTS_hud = 512 512
TXD_OPTS_menu = 512 512
TXD_OPTS_LOADSC0 = 512 512
TXD_OPTS_LOADSC1 = 512 512
TXD_OPTS_LOADSC10 = 512 512
@@ -369,12 +364,15 @@ 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 ?= HALF
TEXTURE_DOWNSAMPLE_IMG ?= NONE
-include texlist.mk
-include modlist.mk
@@ -402,6 +400,11 @@ 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))
@@ -412,12 +415,85 @@ 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)
.PRECIOUS: $(SFX_ORIG) $(SFX_REPACK_DC) $(STREAM_MP3_DECODED) $(STREAM_WAV_DECODED) $(ALL_TEXTURES_ORIG_EXTRACT)
$(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
# 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
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
@@ -456,18 +532,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_IMG_DC_DIR)/%.txd: $(GTA_MOD_IMG_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
@mkdir -p $(@D)
./texconv $< $@ 1024 1024 -e $(PVR_ENCODER) -d NONE
$(REPACK_IMG_DC_DIR)/%.TXD: $(GTA_MOD_IMG_DIR)/%.TXD texconv
$(REPACK_IMG_DC_DIR)/%.TXD: $(GTA_MOD_IMG_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
@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_IMG_DC_DIR)/%.txd: $(REPACK_IMG_ORIG_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
@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_IMG_DC_DIR)/%.TXD: $(REPACK_IMG_ORIG_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
@mkdir -p $(@D)
./texconv $< $@ $(DEFAULT_RES) $(DEFAULT_RES) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_IMG)
@@ -513,26 +589,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)/%.txd: $(GTA_MOD_LOOSE_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
@mkdir -p $(@D)
./texconv $< $@ 1024 1024 -e $(PVR_ENCODER) -d NONE
$(REPACK_GTA_DIR)/%.TXD: $(GTA_MOD_LOOSE_DIR)/%.TXD texconv
$(REPACK_GTA_DIR)/%.TXD: $(GTA_MOD_LOOSE_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
@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)/%.txd: $(GTA_GAMEFILES_LOOSE_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
@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)/%.TXD: $(GTA_GAMEFILES_LOOSE_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
@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)/%.txd: $(GTA_DIR)/%.txd texconv $(REPACK_GTA_DIR)/dc-palette
@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)/%.TXD: $(GTA_DIR)/%.TXD texconv $(REPACK_GTA_DIR)/dc-palette
@mkdir -p $(@D)
./texconv $< $@ $(TXD_OPTS_$(notdir $*)) -e $(PVR_ENCODER) -d $(TEXTURE_DOWNSAMPLE_TXD)

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

View File

@@ -1,6 +1,46 @@
# 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_FILES = $(MISC_TXD) \
anim/cuts.dir \
anim/cuts.img \
anim/gta3.ini \
@@ -136,44 +176,4 @@ MISC_FILES = \
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,7 +118,6 @@ 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 \
@@ -183,15 +182,7 @@ $(TARGET): $(OBJS)
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
$(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
$(REPACK_GTA_DIR)/GTAVCSF8.b: GTAVCSF8.b
mkdir -p $(@D)
cp $< $@
@@ -210,20 +201,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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME).iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME)-no-repack.iso: IP.BIN 1ST_READ.BIN $(REPACK_GTA_DIR)/GTAVCSF8.b
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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME).ds.iso: IP.BIN 1ST_READ.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
rm -f $(PROJECT_NAME).ds.iso
rm -f $(REPACK_GTA_DIR)/1ST_READ.BIN
cp $(TARGET).bin $(REPACK_GTA_DIR)/1ST_READ.BIN
@@ -234,7 +225,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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME)-prebuilt.iso: IP.BIN 1ST_READ_PREBUILT.BIN $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
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)
@@ -253,15 +244,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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME).cdi: $(TARGET) $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME)-no-repack.cdi: $(TARGET) $(REPACK_GTA_DIR)/GTAVCSF8.b
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 $(REPACK_GTA_DIR)/0GDTEX.PVR $(REPACK_GTA_DIR)/settings.ico
$(PROJECT_NAME)-prebuilt.cdi: $(REPACK_DIR)/repacked $(REPACK_GTA_DIR)/GTAVCSF8.b
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

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

View File

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

View File

@@ -11,8 +11,6 @@
#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__)
@@ -49,8 +47,6 @@
/* 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
@@ -74,7 +70,6 @@ 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;
}
@@ -368,13 +363,6 @@ 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) {
@@ -401,28 +389,21 @@ 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;
}
streamf("Stream %d pos: %d, log: %d, played: %d\n", i, channel_pos, logical_pos, streams[i].played_samples);
verbosef("Stream %d pos: %d, log: %d, rem: %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].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;
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;
// 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?
streamf("Filling channel %d with lower half\n", i);
verbosef("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) {
@@ -438,7 +419,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?
streamf("Filling channel %d with upper half\n", i);
verbosef("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) {
@@ -458,7 +439,7 @@ cSampleManager::Initialise(void)
// if end of file, stop
if ((streams[i].played_samples + logical_pos) > streams[i].total_samples) {
// stop channel
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);
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);
aica_stop_chn(streams[i].mapped_ch[0]);
aica_stop_chn(streams[i].mapped_ch[1]);
streams[i].playing = false;
@@ -466,7 +447,7 @@ cSampleManager::Initialise(void)
}
if (do_read) {
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);
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));
CdStreamQueueAudioRead(streams[i].fd, streams[i].buffer, do_read, streams[i].file_offset);
streams[i].file_offset += do_read;
}
@@ -506,7 +487,6 @@ cSampleManager::Initialise(void)
void
cSampleManager::Terminate(void)
{
CdStreamDiscardAudioRead(fdPedSfx);
fs_close(fdPedSfx);
}
@@ -545,7 +525,6 @@ void
cSampleManager::SetMusicMasterVolume(uint8 nVolume)
{
m_nMusicVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -559,7 +538,6 @@ void
cSampleManager::SetMusicFadeVolume(uint8 nVolume)
{
m_nMusicFadeVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -759,9 +737,9 @@ cSampleManager::LoadPedComment(uint32 nComment)
assert(m_aSamples[nComment].nByteSize <= PED_BLOCKSIZE_ADPCM);
CdStreamQueueAudioRead(fdPedSfx, (void*)nPedSlotSfxAddr[nCurrentPedSlot], m_aSamples[nComment].nByteSize, m_aSamples[nComment].nFileOffset, [](AudioReadCmd* cmd) {
CdStreamQueueAudioRead(nComment, (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);
assert(fs_seek(fdPedSfx, cmd->seek, SEEK_SET) == cmd->seek);
fs_seek(fdPedSfx, cmd->seek, SEEK_SET);
// TODO: When we can dma directly to AICA, we can use this instead
@@ -1049,7 +1027,7 @@ cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream, uint32_t seek_by
{
ASSERT( nStream < MAX_STREAMS );
file_t f = fs_open(DCStreamedNameTable[nFile], O_RDONLY);
streamf("PreloadStreamedFile(%p, %d, %d) is %s\n", f, nFile, nStream, DCStreamedNameTable[nFile]);
debugf("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));
@@ -1072,13 +1050,13 @@ cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream, uint32_t seek_by
streams[nStream].next_is_upper_half = true;
streams[nStream].first_refill = true;
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);
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);
// How to avoid the lock?
if (seek_bytes_aligned) {
streams[nStream].played_samples = seek_bytes_aligned * (streams[nStream].stereo ? 1 : 2);
streamf("Seeking aligned to: %d, played_samples: %d\n", seek_bytes_aligned, streams[nStream].played_samples);
debugf("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);
@@ -1107,7 +1085,7 @@ cSampleManager::PreloadStreamedFile(uint8 nFile, uint8 nStream, uint32_t seek_by
streams[nStream].file_offset = fs_tell(f);
}
streamf("PreloadStreamedFile: %p %d - %s, %d, %d, \n", f, nFile, DCStreamedNameTable[nFile], streams[nStream].rate, streams[nStream].stereo);
verbosef("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
@@ -1230,29 +1208,12 @@ 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 alignas(8) CColLine
struct CColLine
{
// NB: this has to be compatible with two CVuVectors
CVector p0;

View File

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

View File

@@ -2,17 +2,12 @@
#include "SurfaceTable.h"
struct alignas(8) CColSphere
struct 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,10 +23,6 @@
#include "Collision.h"
#include "Frontend.h"
#ifdef DC_SH4
#include "VuCollision.h"
#endif
#ifdef VU_COLLISION
#include "VuCollision.h"
@@ -741,12 +737,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
// transform line to model space
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
CColLine newline(matTransform * line.p0, matTransform * line.p1);
// If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(newline, model.boundingBox))
@@ -1586,12 +1577,7 @@ CCollision::ProcessLineOfSight(const CColLine &line,
// transform line to model space
Invert(matrix, matTransform);
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
CColLine newline(matTransform * line.p0, matTransform * line.p1);
// If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(newline, model.boundingBox))
@@ -1615,18 +1601,8 @@ 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;
}
@@ -1763,14 +1739,9 @@ CCollision::ProcessVerticalLine(const CColLine &line,
// transform line to model space
// Why does the game seem to do this differently than above?
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
CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1));
newline.p1.x = newline.p0.x;
newline.p1.y = newline.p0.y;
if(!TestVerticalLineBox(newline, model.boundingBox))
return false;
@@ -1794,31 +1765,14 @@ 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;
}
@@ -2169,60 +2123,25 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
assert(modelA.numLines <= MAXNUMLINES);
// From model A space to model B space
Invert(matrixB, matAB);
#ifndef DC_SH4
matAB = Invert(matrixB, matAB);
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++) {
#ifndef DC_SH4
for(i = 0; i < modelA.numLines; i++)
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;
@@ -2241,26 +2160,9 @@ 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;
}
@@ -2307,22 +2209,9 @@ 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
@@ -2353,17 +2242,8 @@ 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,7 +479,6 @@ RemoveFirstInQueue(Queue *queue)
}
std::vector<AudioReadCmd> pendingAudioReads;
volatile int pendingAudioRead_fd = -1;
#if !defined(DC_SH4)
std::mutex pendingAudioReadsMutex;
#endif
@@ -488,9 +487,8 @@ 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){
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);
lseek(cmd->fd, cmd->seek, SEEK_SET);
read(cmd->fd, cmd->dest, cmd->size);
};
} else {
cmd.callback = callback;
@@ -502,7 +500,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) {
if (it->fd == -1 || it->fd == fd) {
*it = cmd;
goto out;
}
@@ -534,12 +532,6 @@ 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() {
@@ -556,8 +548,6 @@ AudioReadCmd CdStreamNextAudioRead() {
break;
}
}
assert(pendingAudioRead_fd == -1);
pendingAudioRead_fd = cmd.fd;
#if defined(DC_SH4)
irq_restore(mask);
#endif
@@ -578,7 +568,6 @@ 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();
}
}
@@ -595,7 +584,6 @@ void *CdStreamThread(void *param)
auto cmd = CdStreamNextAudioRead();
while (cmd.fd != -1) {
cmd.callback(&cmd);
pendingAudioRead_fd = -1;
cmd = CdStreamNextAudioRead();
}

View File

@@ -692,383 +692,118 @@ 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[] = {
"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",
"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",
""
};
char *OptimizedNames[] = {

View File

@@ -94,10 +94,6 @@
#include <sys/stat.h>
#include <cctype>
#ifdef DC_SH4
#include <dc/vmu_pkg.h>
#endif
namespace mINI
{
namespace INIStringUtil
@@ -339,7 +335,6 @@ namespace mINI
private:
std::ifstream fileReadStream;
T_LineDataPtr lineData;
std::size_t start_offt;
T_LineData readFile()
{
@@ -348,7 +343,7 @@ namespace mINI
fileContents.resize(fileReadStream.tellg());
fileReadStream.seekg(0, std::ios::beg);
std::size_t fileSize = fileContents.size();
fileReadStream.read(const_cast<char *>(fileContents.c_str()), fileSize);
fileReadStream.read(&fileContents[0], fileSize);
fileReadStream.close();
T_LineData output;
if (fileSize == 0)
@@ -357,19 +352,7 @@ namespace mINI
}
std::string buffer;
buffer.reserve(50);
#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)
for (std::size_t i = 0; i < fileSize; ++i)
{
char& c = fileContents[i];
if (c == '\n')
@@ -395,8 +378,6 @@ namespace mINI
{
lineData = std::make_shared<T_LineData>();
}
start_offt = 0;
}
~INIReader() { }
@@ -445,71 +426,22 @@ 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, bool prettyPrint_=false)
: fileWriteStream(filename, std::ios::out | std::ios::binary),
prettyPrint(prettyPrint_)
INIGenerator(std::string const& filename)
{
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;
fileWriteStream.open(filename, std::ios::out | std::ios::binary);
}
~INIGenerator() { }
bool operator<<(INIStructure const& data)
{
if (!fileWriteStream.is_open())
{
return false;
}
if (!data.size())
{
return true;
@@ -519,13 +451,13 @@ namespace mINI
{
auto const& section = it->first;
auto const& collection = it->second;
memStream
fileWriteStream
<< "["
<< section
<< "]";
if (collection.size())
{
memStream << INIStringUtil::endl;
fileWriteStream << INIStringUtil::endl;
auto it2 = collection.begin();
for (;;)
{
@@ -533,7 +465,7 @@ namespace mINI
INIStringUtil::replace(key, "=", "\\=");
auto value = it2->second;
INIStringUtil::trim(value);
memStream
fileWriteStream
<< key
<< ((prettyPrint) ? " = " : "=")
<< value;
@@ -541,29 +473,21 @@ namespace mINI
{
break;
}
memStream << INIStringUtil::endl;
fileWriteStream << INIStringUtil::endl;
}
}
if (++it == data.end())
{
break;
}
memStream << INIStringUtil::endl;
fileWriteStream << INIStringUtil::endl;
if (prettyPrint)
{
memStream << INIStringUtil::endl;
fileWriteStream << 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
@@ -743,15 +667,12 @@ namespace mINI
{
struct stat buf;
bool fileExists = (stat(filename.c_str(), &buf) == 0);
if (!fileExists)
{
if(INIGenerator generator(filename, prettyPrint); generator) {
generator << data;
}
return INIGenerator::wasGood();
INIGenerator generator(filename);
generator.prettyPrint = prettyPrint;
return generator << data;
}
INIStructure originalData;
T_LineDataPtr lineData;
bool readSuccess = false;
@@ -767,21 +688,23 @@ 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 (INIGenerator generator(filename, prettyPrint); generator && output.size())
if (output.size())
{
auto line = output.begin();
for (;;)
{
generator << *line;
fileWriteStream << *line;
if (++line == output.end())
{
break;
}
generator << INIStringUtil::endl;
fileWriteStream << INIStringUtil::endl;
}
}
return INIGenerator::wasGood();
return true;
}
return false;
}
@@ -818,10 +741,9 @@ namespace mINI
{
return false;
}
if(INIGenerator generator(filename, pretty); generator) {
generator << data;
}
return INIGenerator::wasGood();
INIGenerator generator(filename);
generator.prettyPrint = pretty;
return generator << data;
}
bool write(INIStructure& data, bool pretty = false) const
{

View File

@@ -1,5 +1,11 @@
#include "common.h"
CMatrix::CMatrix(void)
{
m_attachment = nil;
m_hasRwMatrix = false;
}
CMatrix::CMatrix(CMatrix const &m)
{
m_attachment = nil;
@@ -504,9 +510,14 @@ 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));
#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
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 alignas(8) CMatrix
class CMatrix
{
public:
union
@@ -8,17 +8,17 @@ public:
alignas(8) float f[4][4];
struct alignas(8)
{
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;
float rx, ry, rz, rw;
float fx, fy, fz, fw;
float ux, uy, uz, uw;
float px, py, pz, pw;
};
};
RwMatrix *m_attachment = nil;
bool m_hasRwMatrix = false; // are we the owner?
RwMatrix *m_attachment;
bool m_hasRwMatrix; // 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_single3_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z);
mat_trans_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z, out.y);
#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_single3_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z);
mat_trans_nodiv_nomod(in.x, in.y, in.z, out.x, out.y, out.z, out.y);
#else
out = mat * in;
#endif
@@ -80,6 +80,7 @@ __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\
@@ -109,11 +110,9 @@ __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)));
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;
}
mat_transform(reinterpret_cast<vector_t *>(const_cast<RwV3d *>(in)),
reinterpret_cast<vector_t *>(out),
n, stride - sizeof(vector_t));
#else
while(n--){
*out = mat * *in;

View File

@@ -39,11 +39,7 @@
#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,11 +58,7 @@ public:
};
enum {
#ifdef RW_DC
NUM_RAIN_STREAKS = 10
#elif
NUM_RAIN_STREAKS = 35
#endif
};
struct tRainStreak

View File

@@ -5220,10 +5220,6 @@ 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,7 +198,6 @@ public:
char GetCDAudioDriveLetter (void);
void UpdateEffectsVolume(void);
void UpdateStreamsVolume(void);
#ifdef DC_SH4
void UpdateChannelVolume(uint32 nChannel);

View File

@@ -12,8 +12,6 @@
#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__)
@@ -48,8 +46,6 @@
/* 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
@@ -73,7 +69,6 @@ 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;
}
@@ -375,12 +370,6 @@ 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) {
@@ -407,27 +396,21 @@ 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;
}
streamf("Stream %d pos: %d, log: %d, played: %d\n", i, channel_pos, logical_pos, streams[i].played_samples);
verbosef("Stream %d pos: %d, log: %d, rem: %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].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;
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;
// 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?
streamf("Filling channel %d with lower half\n", i);
verbosef("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) {
@@ -443,7 +426,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?
streamf("Filling channel %d with upper half\n", i);
verbosef("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) {
@@ -463,7 +446,7 @@ cSampleManager::Initialise(void)
// if end of file, stop
if ((streams[i].played_samples + logical_pos) > streams[i].total_samples) {
// stop channel
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);
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);
aica_stop_chn(streams[i].mapped_ch[0]);
aica_stop_chn(streams[i].mapped_ch[1]);
streams[i].playing = false;
@@ -471,7 +454,7 @@ cSampleManager::Initialise(void)
}
if (do_read) {
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);
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));
CdStreamQueueAudioRead(streams[i].fd, streams[i].buffer, do_read, streams[i].file_offset);
streams[i].file_offset += do_read;
}
@@ -511,7 +494,6 @@ cSampleManager::Initialise(void)
void
cSampleManager::Terminate(void)
{
CdStreamDiscardAudioRead(fdPedSfx);
fs_close(fdPedSfx);
}
@@ -538,6 +520,7 @@ cSampleManager::UpdateEffectsVolume(void)
}
}
void
cSampleManager::SetEffectsMasterVolume(uint8 nVolume)
{
@@ -549,7 +532,6 @@ void
cSampleManager::SetMusicMasterVolume(uint8 nVolume)
{
m_nMusicVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -569,7 +551,6 @@ void
cSampleManager::SetMusicFadeVolume(uint8 nVolume)
{
m_nMusicFadeVolume = nVolume;
UpdateStreamsVolume();
}
void
@@ -715,8 +696,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(fdPedSfx, (void*)gPlayerTalkData, m_aSamples[nSample].nByteSize, m_aSamples[nSample].nFileOffset, [](AudioReadCmd* cmd) {
assert(fs_seek(fdPedSfx, cmd->seek, SEEK_SET) == cmd->seek);
CdStreamQueueAudioRead(nSample, (void*)gPlayerTalkData, m_aSamples[nSample].nByteSize, m_aSamples[nSample].nFileOffset, [](AudioReadCmd* cmd) {
fs_seek(fdPedSfx, cmd->seek, SEEK_SET);
// 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);
@@ -812,8 +793,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(fdPedSfx, (void*)nPedSlotSfxAddr[nCurrentPedSlot], m_aSamples[nComment].nByteSize, m_aSamples[nComment].nFileOffset, [](AudioReadCmd* cmd) {
assert(fs_seek(fdPedSfx, cmd->seek, SEEK_SET) == cmd->seek);
CdStreamQueueAudioRead(nComment, (void*)nPedSlotSfxAddr[nCurrentPedSlot], m_aSamples[nComment].nByteSize, m_aSamples[nComment].nFileOffset, [](AudioReadCmd* cmd) {
fs_seek(fdPedSfx, cmd->seek, SEEK_SET);
// TODO: When we can dma directly to AICA, we can use this instead
@@ -1117,7 +1098,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);
streamf("PreloadStreamedFile(%p, %d, %d) is %s\n", f, nFile, nStream, DCStreamedNameTable[nFile]);
debugf("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));
@@ -1149,13 +1130,13 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream, uint32_t seek_b
streams[nStream].next_is_upper_half = true;
streams[nStream].first_refill = true;
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);
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);
// How to avoid the lock?
if (seek_bytes_aligned) {
streams[nStream].played_samples = seek_bytes_aligned * (streams[nStream].stereo ? 1 : 2);
streamf("Seeking aligned to: %d, played_samples: %d\n", seek_bytes_aligned, streams[nStream].played_samples);
debugf("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);
@@ -1184,7 +1165,7 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream, uint32_t seek_b
streams[nStream].file_offset = fs_tell(f);
}
streamf("PreloadStreamedFile: %p %d - %s, %d, %d, \n", f, nFile, DCStreamedNameTable[nFile], streams[nStream].rate, streams[nStream].stereo);
verbosef("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
@@ -1311,28 +1292,12 @@ 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 alignas(8) CColLine
struct CColLine
{
// NB: this has to be compatible with two CVuVectors
CVector p0;

View File

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

View File

@@ -2,7 +2,7 @@
#include "SurfaceTable.h"
struct alignas(8) CSphere
struct CSphere
{
// NB: this has to be compatible with a CVuVector
CVector center;
@@ -15,11 +15,6 @@ 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,10 +24,6 @@
#include "Camera.h"
#include "ColStore.h"
#ifdef DC_SH4
#include "VuCollision.h"
#endif
#ifdef VU_COLLISION
#include "VuCollision.h"
@@ -576,12 +572,7 @@ CCollision::TestLineOfSight(const CColLine &line, const CMatrix &matrix, CColMod
// transform line to model space
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
CColLine newline(matTransform * line.p0, matTransform * line.p1);
// If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(newline, model.boundingBox))
@@ -1437,12 +1428,7 @@ CCollision::ProcessLineOfSight(const CColLine &line,
// transform line to model space
Invert(matrix, matTransform);
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
CColLine newline(matTransform * line.p0, matTransform * line.p1);
// If we don't intersect with the bounding box, no chance on the rest
if(!TestLineBox(newline, model.boundingBox))
@@ -1469,18 +1455,8 @@ 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;
}
@@ -1617,14 +1593,7 @@ CCollision::ProcessVerticalLine(const CColLine &line,
// transform line to model space
// Why does the game seem to do this differently than above?
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
CColLine newline(MultiplyInverse(matrix, line.p0), MultiplyInverse(matrix, line.p1));
if(!TestLineBox(newline, model.boundingBox))
return false;
@@ -1649,29 +1618,13 @@ 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;
@@ -2023,60 +1976,26 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA,
assert(modelA.numLines <= MAXNUMLINES);
// From model A space to model B space
Invert(matrixB, matAB);
#ifndef DC_SH4
matAB = Invert(matrixB, matAB);
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++) {
#ifndef DC_SH4
for(i = 0; i < modelA.numLines; i++)
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;
@@ -2094,26 +2013,9 @@ 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;
}
@@ -2160,22 +2062,9 @@ 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
@@ -2206,17 +2095,8 @@ 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,7 +479,6 @@ RemoveFirstInQueue(Queue *queue)
}
std::vector<AudioReadCmd> pendingAudioReads;
volatile int pendingAudioRead_fd = -1;
#if !defined(DC_SH4)
std::mutex pendingAudioReadsMutex;
#endif
@@ -488,9 +487,8 @@ 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){
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);
lseek(cmd->fd, cmd->seek, SEEK_SET);
read(cmd->fd, cmd->dest, cmd->size);
};
} else {
cmd.callback = callback;
@@ -502,7 +500,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) {
if (it->fd == -1 || it->fd == fd) {
*it = cmd;
goto out;
}
@@ -534,12 +532,6 @@ 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() {
@@ -556,8 +548,6 @@ AudioReadCmd CdStreamNextAudioRead() {
break;
}
}
assert(pendingAudioRead_fd == -1);
pendingAudioRead_fd = cmd.fd;
#if defined(DC_SH4)
irq_restore(mask);
#endif
@@ -578,7 +568,6 @@ 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();
}
}
@@ -595,7 +584,6 @@ void *CdStreamThread(void *param)
auto cmd = CdStreamNextAudioRead();
while (cmd.fd != -1) {
cmd.callback(&cmd);
pendingAudioRead_fd = -1;
cmd = CdStreamNextAudioRead();
}

View File

@@ -718,671 +718,269 @@ CFileLoader::LoadObjectTypes(const char *filename)
//find . -type f -name "*rail*.dff" ! -name "*shad*"
//find . -type f -name "*veg*.dff" ! -name "*shad*"
char *AlphaTestNames[] = {
"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",
"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",
"",
};

View File

@@ -68,9 +68,6 @@ 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;
@@ -732,10 +729,10 @@ CMenuManager::CheckSliderMovement(int value)
break;
case MENUACTION_DRAWDIST:
if(value > 0)
m_PrefsLOD += ((MAX_DRAWDIST - MIN_DRAWDIST) / MENUSLIDER_LOGICAL_BARS);
m_PrefsLOD += ((1.8f - 0.925f) / MENUSLIDER_LOGICAL_BARS);
else
m_PrefsLOD -= ((MAX_DRAWDIST - MIN_DRAWDIST) / MENUSLIDER_LOGICAL_BARS);
m_PrefsLOD = Clamp(m_PrefsLOD, MIN_DRAWDIST, MAX_DRAWDIST);
m_PrefsLOD -= ((1.8f - 0.925f) / MENUSLIDER_LOGICAL_BARS);
m_PrefsLOD = Clamp(m_PrefsLOD, 0.925f, 1.8f);
CRenderer::ms_lodDistScale = m_PrefsLOD;
break;
@@ -1565,7 +1562,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 - MIN_DRAWDIST) / (MAX_DRAWDIST - MIN_DRAWDIST), SLIDER_Y(99.0f), HOVEROPTION_INCREASE_DRAWDIST, HOVEROPTION_DECREASE_DRAWDIST, SCREEN_WIDTH, true);
ProcessSlider((m_PrefsLOD - 0.925f) / 0.875f, 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,10 +2026,6 @@ 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
{
@@ -2052,13 +2048,8 @@ 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
}
}
@@ -2085,10 +2076,6 @@ 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)
@@ -2145,12 +2132,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)
@@ -3528,15 +3515,16 @@ bool CPad::CycleCameraModeJustDown(void)
bool result;
switch (CURMODE)
{
case 0: //audible feedback when changing camera ?
case 0:
case 2:
case 3:
{
result = !!(NewState.DPadUp && !OldState.DPadUp);
result = !!(NewState.Select && !OldState.Select);
break;
}
case 1: //audible feedback when changing camera ?
case 1:
{
result = !!(NewState.DPadUp && !OldState.DPadUp);
@@ -3553,9 +3541,9 @@ bool CPad::CycleCameraModeJustDown(void)
{
switch (CURMODE)
{
case 1: //audible feedback when changing camera ?
case 1:
{
result = !!(NewState.DPadUp && !OldState.DPadUp);
result = !!(NewState.DPadDown && !OldState.DPadDown);
break;
}
default:
@@ -3881,49 +3869,36 @@ bool CPad::CollectPickupJustDown(void)
return false;
}
bool CPad::DuckJustDown(void)
bool CPad::DuckJustDown(void)
{
if (ArePlayerControlsDisabled()) {
duckFrameCounter = 0;
if (ArePlayerControlsDisabled())
return false;
}
#ifdef RW_DC
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;
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);
}
}
return false;
#else
bool buttonPressed = NewState.Square;
if (buttonPressed) {
duckFrameCounter++;
if (duckFrameCounter >= DUCK_DELAY_FRAMES && !isDucking) {
isDucking = true;
return true;
}
} else {
duckFrameCounter = 0;
isDucking = false;
}
return false;
return !!(NewState.LeftShock && !OldState.LeftShock);
#endif
}

View File

@@ -173,26 +173,11 @@ 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() : 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() { }
~CPad() { }
static bool bDisplayNoControllerMessage;

View File

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

View File

@@ -94,10 +94,6 @@
#include <sys/stat.h>
#include <cctype>
#ifdef DC_SH4
#include <dc/vmu_pkg.h>
#endif
namespace mINI
{
namespace INIStringUtil
@@ -339,7 +335,6 @@ namespace mINI
private:
std::ifstream fileReadStream;
T_LineDataPtr lineData;
std::size_t start_offt;
T_LineData readFile()
{
@@ -348,7 +343,7 @@ namespace mINI
fileContents.resize(fileReadStream.tellg());
fileReadStream.seekg(0, std::ios::beg);
std::size_t fileSize = fileContents.size();
fileReadStream.read(const_cast<char *>(fileContents.c_str()), fileSize);
fileReadStream.read(&fileContents[0], fileSize);
fileReadStream.close();
T_LineData output;
if (fileSize == 0)
@@ -357,19 +352,7 @@ namespace mINI
}
std::string buffer;
buffer.reserve(50);
#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)
for (std::size_t i = 0; i < fileSize; ++i)
{
char& c = fileContents[i];
if (c == '\n')
@@ -395,8 +378,6 @@ namespace mINI
{
lineData = std::make_shared<T_LineData>();
}
start_offt = 0;
}
~INIReader() { }
@@ -445,71 +426,22 @@ 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, bool prettyPrint_=false)
: fileWriteStream(filename, std::ios::out | std::ios::binary),
prettyPrint(prettyPrint_)
INIGenerator(std::string const& filename)
{
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;
fileWriteStream.open(filename, std::ios::out | std::ios::binary);
}
~INIGenerator() { }
bool operator<<(INIStructure const& data)
{
if (!fileWriteStream.is_open())
{
return false;
}
if (!data.size())
{
return true;
@@ -519,13 +451,13 @@ namespace mINI
{
auto const& section = it->first;
auto const& collection = it->second;
memStream
fileWriteStream
<< "["
<< section
<< "]";
if (collection.size())
{
memStream << INIStringUtil::endl;
fileWriteStream << INIStringUtil::endl;
auto it2 = collection.begin();
for (;;)
{
@@ -533,7 +465,7 @@ namespace mINI
INIStringUtil::replace(key, "=", "\\=");
auto value = it2->second;
INIStringUtil::trim(value);
memStream
fileWriteStream
<< key
<< ((prettyPrint) ? " = " : "=")
<< value;
@@ -541,29 +473,21 @@ namespace mINI
{
break;
}
memStream << INIStringUtil::endl;
fileWriteStream << INIStringUtil::endl;
}
}
if (++it == data.end())
{
break;
}
memStream << INIStringUtil::endl;
fileWriteStream << INIStringUtil::endl;
if (prettyPrint)
{
memStream << INIStringUtil::endl;
fileWriteStream << 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
@@ -743,15 +667,12 @@ namespace mINI
{
struct stat buf;
bool fileExists = (stat(filename.c_str(), &buf) == 0);
if (!fileExists)
{
if(INIGenerator generator(filename, prettyPrint); generator) {
generator << data;
}
return INIGenerator::wasGood();
INIGenerator generator(filename);
generator.prettyPrint = prettyPrint;
return generator << data;
}
INIStructure originalData;
T_LineDataPtr lineData;
bool readSuccess = false;
@@ -767,21 +688,23 @@ 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 (INIGenerator generator(filename, prettyPrint); generator && output.size())
if (output.size())
{
auto line = output.begin();
for (;;)
{
generator << *line;
fileWriteStream << *line;
if (++line == output.end())
{
break;
}
generator << INIStringUtil::endl;
fileWriteStream << INIStringUtil::endl;
}
}
return INIGenerator::wasGood();
return true;
}
return false;
}
@@ -818,10 +741,9 @@ namespace mINI
{
return false;
}
if(INIGenerator generator(filename, pretty); generator) {
generator << data;
}
return INIGenerator::wasGood();
INIGenerator generator(filename);
generator.prettyPrint = pretty;
return generator << data;
}
bool write(INIStructure& data, bool pretty = false) const
{

View File

@@ -1,5 +1,11 @@
#include "common.h"
CMatrix::CMatrix(void)
{
m_attachment = nil;
m_hasRwMatrix = false;
}
CMatrix::CMatrix(CMatrix const &m)
{
m_attachment = nil;
@@ -428,11 +434,6 @@ 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;
@@ -445,7 +446,6 @@ 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 alignas(8) CMatrix
class CMatrix
{
public:
#ifdef GTA_PS2
@@ -23,18 +23,18 @@ public:
float f[4][4];
struct
{
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;
float rx, ry, rz, rw;
float fx, fy, fz, fw;
float ux, uy, uz, uw;
float px, py, pz, pw;
};
};
RwMatrix *m_attachment=nil;
bool m_hasRwMatrix=false; // are we the owner?
RwMatrix *m_attachment;
bool m_hasRwMatrix; // 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,14 +1,6 @@
#pragma once
#include "maths.h"
#ifdef RW_DC
#define VECTOR_ALIGN 8
#else
#define VECTOR_ALIGN 16
#endif
class TYPEALIGN(VECTOR_ALIGN) CVuVector : public CVector
class TYPEALIGN(16) CVuVector : public CVector
{
public:
float w;
@@ -34,123 +26,7 @@ public:
// TODO: operator-
};
__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
}
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);

View File

@@ -3,3 +3,116 @@
#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,32 +1,5 @@
#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,11 +60,7 @@ public:
};
enum {
#ifdef RW_DC
NUM_RAIN_STREAKS = 10
#elif
NUM_RAIN_STREAKS = 35
#endif
};
struct tRainStreak

View File

@@ -0,0 +1,69 @@
#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;
}

128
src/tools/pal-clusters.py Normal file
View File

@@ -0,0 +1,128 @@
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,6 +67,7 @@ namespace rw::dc {
extern int32 maxRasterHeight;
extern int32 downsampleMode;
extern int32 pvrEncoder;
extern const char* dstFile;
}
RwTexDictionary *LoadTxd(RwStream *stream);
@@ -307,6 +308,8 @@ 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;
}
}
}
@@ -344,6 +347,8 @@ 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");
@@ -378,12 +383,14 @@ int main(int argc, const char** argv) {
}
}
auto streamOut = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, argv[2]);
assert(streamOut && "failed to open output");
StoreTxd(texDict, streamOut);
RwStreamClose(streamOut, nil);
if (rw::dc::pvrEncoder != EXTRACT) {
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,6 +10,7 @@
#endif
#if defined(DC_TEXCONV)
#include <fcntl.h>
#include "tri_stripper.h"
#include <sha256.h>
extern const char* currentFile;
@@ -575,7 +576,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) != PVR_GET(PVR_TA_OPB_INIT));
PVR_GET(PVR_TA_OPB_POS)*4 >= PVR_GET(PVR_TA_OPB_END);
}
constexpr size_t freeVertexTarget_Step_Up = 32 * 1024;
@@ -1036,7 +1037,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.
@@ -1080,7 +1081,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)...);
}
@@ -1093,27 +1094,8 @@ 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([=]() {
@@ -1223,11 +1205,6 @@ 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);
@@ -4624,6 +4601,7 @@ int32 maxRasterWidth = 64;
int32 maxRasterHeight = 64;
int32 downsampleMode = NONE;
int32 pvrEncoder = PVRTEX;
const char* dstFile;
#endif
bool32
@@ -4796,6 +4774,11 @@ 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);
@@ -4820,50 +4803,99 @@ rasterFromImage(Raster* raster, Image* image)
fprintf(stderr, "Failed to write TGA file: %s\n", filename_tga);
return false;
}
if (pvrEncoder != EXTRACT) {
char encodeCommand[512];
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";
// 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
}
int cluster = -1;
FILE* fclust = fopen(clusterfile.str().c_str(), "r");
if (!fclust) {
fprintf(stderr, "cluster: %s\n", clusterfile.str().c_str());
}
assert(fclust);
int retCode = system(encodeCommand);
fscanf(fclust, "%d", &cluster);
fclose(fclust);
// Read PVR File
assert(raster->width && raster->height && !natras->raster->texaddr);
loadPVR(filename_pvr, raster, natras->raster, PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE);
assert(cluster >= 0 && cluster <= 64);
remove(filename_tga);
remove(filename_pvr);
// 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;
}
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);
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);
}
if(truecolimg)
@@ -5001,6 +5033,14 @@ 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)
{
@@ -5030,10 +5070,10 @@ deviceSystem(DeviceReq req, void *arg0, int32 n)
case DEVICEGETVIDEOMODEINFO:{
auto rwmode = (VideoMode*)arg0;
rwmode->width = videoModes[n].width;
rwmode->height = videoModes[n].height;
rwmode->depth = videoModes[n].depth;
rwmode->flags = videoModes[n].flags;
rwmode->width = 640;
rwmode->height = 480;
rwmode->depth = 16;
rwmode->flags = VIDEOMODEEXCLUSIVE;
return 1;
}
case DEVICEGETMAXMULTISAMPLINGLEVELS:
@@ -5044,19 +5084,22 @@ 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 VIDEO_MODES;
return 1;
case DEVICEGETCURRENTVIDEOMODE:
return VIDEO_MODE;
return 0;
case DEVICESETVIDEOMODE:
VIDEO_MODE = n;
return 1;
default:
assert(0 && "not implemented");
@@ -5137,32 +5180,33 @@ 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
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);
#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]);
}
#endif
fake_tex = pvr_mem_malloc(sizeof(fake_tex_data));
#if !defined(DC_SIM)
@@ -5286,9 +5330,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)) {
if (((uintptr_t)src & 31) || pvr_size & 31) {
dcache_pref_block(src);
if ((uintptr_t)src & 3) {

View File

@@ -21,7 +21,8 @@ enum downsampleModes {
enum pvrEncoders {
PVRTOOL,
PVRTEX
PVRTEX,
EXTRACT
};
// TGA Header Struct
@@ -141,6 +142,10 @@ 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;
@@ -153,11 +158,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 & 255) == 0);
} else {
assert((natras->texsize & 31) == 0);
}
// if (natras->texsize >= 256) {
// assert((natras->texsize & 31) == 0);
// } else {
// assert((natras->texsize & 31) == 0);
// }
fclose(tex);
}

View File

@@ -53,7 +53,8 @@ void fPvrWrite(const PvrTexEncoder *pte, const char *outfname) {
}
if (pteIsPalettized(pte))
ErrorExit(".PVR format does not support compressed palettized textures\n");
idxcnt/= 4;
// 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_PROGRESS;
int log_level = LOG_DEBUG;
void pteLogLocV(unsigned level, const char *file, unsigned line, const char *fmt, va_list args) {
static const char * logtypes[] = {
[LOG_ALL] = "ALL",
@@ -163,10 +163,11 @@ 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 11
#define MAX_FNAMES 1024
const char *fnames[MAX_FNAMES];
unsigned fname_cnt = 0;
const char *outname = "";
@@ -298,6 +299,23 @@ 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);
}
@@ -390,6 +408,34 @@ 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,6 +446,15 @@ 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 (11)
#define PVR_MAX_MIPMAPS (1024)
#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,7 +288,38 @@ 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,6 +202,7 @@ 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, ...);