Compare commits
55 Commits
alpha
...
pGta-Menu-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2d7ce9132 | ||
|
|
3188550311 | ||
|
|
9a1ea298d9 | ||
|
|
383442c6aa | ||
|
|
9b775dff3f | ||
|
|
353b7cc56d | ||
|
|
52c4946111 | ||
|
|
77b40f3004 | ||
|
|
ff2368da21 | ||
|
|
4ac38c0d64 | ||
|
|
ed2898ae2a | ||
|
|
a14f51246d | ||
|
|
19f22e8edb | ||
|
|
354b1ae92c | ||
|
|
a6a1fdb9cb | ||
|
|
309232c221 | ||
|
|
70df292c7a | ||
|
|
554a668897 | ||
|
|
3998368791 | ||
|
|
730302180a | ||
|
|
87bfbcab2d | ||
|
|
bdc27bf2fc | ||
|
|
1ee51d5136 | ||
|
|
725d60a9fb | ||
|
|
05e9e7452e | ||
|
|
51b21c02b9 | ||
|
|
86806215a5 | ||
|
|
a056fdecc7 | ||
|
|
b6d5c628b2 | ||
|
|
8c81349c69 | ||
|
|
282b639a4c | ||
|
|
69f9bbcf7b | ||
|
|
40f212e131 | ||
|
|
43c0e99ebf | ||
|
|
42647ddc6b | ||
|
|
b3ccf1f900 | ||
|
|
baf7612fcf | ||
|
|
33b9dd1c8a | ||
|
|
5786eeecb8 | ||
|
|
20864fdac6 | ||
|
|
1587d707a8 | ||
|
|
911b93bd0f | ||
|
|
e86fb27a48 | ||
|
|
2065c9a93f | ||
|
|
a2caa56275 | ||
|
|
fa65f637ad | ||
|
|
0a0a664428 | ||
|
|
5abd0641a4 | ||
|
|
ca866bdb2a | ||
|
|
bf0e36858e | ||
|
|
b90e8433da | ||
|
|
133110c15c | ||
|
|
6f71cfc458 | ||
|
|
02d0103b20 | ||
|
|
72da27ef0b |
@@ -28,12 +28,12 @@ You will also need the following tools installed
|
||||
|
||||
### Cloning the dca3-game repo and downloading the prebuilt elf
|
||||
- Open dreamsdk shell
|
||||
- type `git clone https://gitlab.com/skmp/dca3-game.git` (and press enter)
|
||||
- type `git clone --branch alpha https://gitlab.com/skmp/dca3-game.git` (and press enter)
|
||||
- It should take a moment and successfully clone the repo
|
||||
- type `cd dca3-game/dreamcast` (and press enter)
|
||||
- type `explorer .` (and press enter).
|
||||
- A folder named dreamcast with some files should be open. Keep it on the side.
|
||||
- Download the artifacts from https://gitlab.com/skmp/dca3-game/-/jobs/8725216645
|
||||
- Download the Alpha Prebuilt Elf from https://gitlab.com/skmp/dca3-game/-/releases
|
||||
- Open artifacts.zip and extract dca3.elf to the folder that was kept open before.
|
||||
- Close the folder and dreamsdk shell
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ OBJS_TEXCONV += \
|
||||
../vendor/librw/src/d3d-x/d3d.texconv.o \
|
||||
../vendor/librw/src/d3d-x/d3d8.texconv.o \
|
||||
../vendor/librw/src/d3d-x/d3d8render.texconv.o \
|
||||
../vendor/librw/src/bmp.texconv.o \
|
||||
../vendor/librw/src/png.texconv.o \
|
||||
../vendor/librw/src/lodepng/lodepng.texconv.o
|
||||
|
||||
# Add compilation units to this list to explicity compile them with
|
||||
# -O3 optimizations, while the rest get the default (-Os) treatment
|
||||
@@ -283,7 +286,17 @@ texconv: $(OBJS_TEXCONV) | pvrtex # You'll have to rebuild pvrtex manually if yo
|
||||
|
||||
TXD_OPTS_fonts = 256 256
|
||||
TXD_OPTS_hud = 128 128
|
||||
TXD_OPTS_menu = 512 512
|
||||
TXD_OPTS_menu = 512 512 \
|
||||
--include-tex assets/mapBot01.png mapBot01 \
|
||||
--include-tex assets/mapBot02.png mapBot02 \
|
||||
--include-tex assets/mapBot03.png mapBot03 \
|
||||
--include-tex assets/mapMid01.png mapMid01 \
|
||||
--include-tex assets/mapMid02.png mapMid02 \
|
||||
--include-tex assets/mapMid03.png mapMid03 \
|
||||
--include-tex assets/mapTop01.png mapTop01 \
|
||||
--include-tex assets/mapTop02.png mapTop02 \
|
||||
--include-tex assets/mapTop03.png mapTop03
|
||||
|
||||
TXD_OPTS_LOADSC0 = 512 512
|
||||
TXD_OPTS_LOADSC1 = 512 512
|
||||
TXD_OPTS_LOADSC10 = 512 512
|
||||
@@ -316,6 +329,22 @@ TXD_OPTS_NEWS = 512 512
|
||||
TXD_OPTS_SPLASH1 = 512 512
|
||||
TXD_OPTS_SPLASH2 = 512 512
|
||||
TXD_OPTS_SPLASH3 = 512 512
|
||||
TXD_OPTS_frontend = 512 512 \
|
||||
--delete-tex "fe_arrows4" \
|
||||
--delete-tex "fe_arrows2" \
|
||||
--delete-tex "fe_arrows1" \
|
||||
--delete-tex "fe_controllersh" \
|
||||
--delete-tex "fe_controller" \
|
||||
\
|
||||
--include-tex assets/dc_ps2d.png dc_ps2d \
|
||||
--include-tex assets/dc_ps2f.png dc_ps2f \
|
||||
--include-tex assets/dc_xboxd.png dc_xboxd \
|
||||
--include-tex assets/dc_xboxf.png dc_xboxf \
|
||||
--include-tex assets/ps4_d.png ps4_d \
|
||||
--include-tex assets/ps4_f.png ps4_f \
|
||||
--include-tex assets/xbox_d.png xbox_d \
|
||||
--include-tex assets/xbox_f.png xbox_f
|
||||
|
||||
DEFAULT_RES = 512
|
||||
|
||||
PVR_ENCODER ?= PVRTEX
|
||||
|
||||
BIN
dreamcast/assets/dc_ps2d.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
dreamcast/assets/dc_ps2f.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
dreamcast/assets/dc_xboxd.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
dreamcast/assets/dc_xboxf.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
dreamcast/assets/ps4_d.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
dreamcast/assets/ps4_f.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
dreamcast/assets/xbox_d.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
dreamcast/assets/xbox_f.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
@@ -3,6 +3,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
@@ -238,6 +239,40 @@ PluginAttach(void)
|
||||
|
||||
const char* currentFile;
|
||||
|
||||
namespace rw {
|
||||
Image* readBMP(const char *filename);
|
||||
Image* readPNG(const char *filename);
|
||||
}
|
||||
|
||||
void InsertImage(RwTexDictionary* texDict, const char* file, const char* texName) {
|
||||
RwTexture *tex;
|
||||
RwRaster *raster;
|
||||
RwInt32 width, height, depth, format;
|
||||
RwImage *image = rw::readBMP(file);
|
||||
if (!image) {
|
||||
image = rw::readPNG(file);
|
||||
}
|
||||
|
||||
assert(image);
|
||||
|
||||
RwImageFindRasterFormat(image, rwRASTERTYPETEXTURE, &width, &height, &depth, &format);
|
||||
raster = RwRasterCreate(width, height, depth, format);
|
||||
RwRasterSetFromImage(raster, image);
|
||||
|
||||
tex = RwTextureCreate(raster);
|
||||
RwTextureSetName(tex, texName);
|
||||
|
||||
RwTextureSetFilterMode(tex, rwFILTERLINEAR);
|
||||
|
||||
RwTexDictionaryAddTexture(texDict, tex);
|
||||
|
||||
RwImageDestroy(image);
|
||||
}
|
||||
|
||||
std::vector<std::pair<const char*, const char*>> ImagesToAdd;
|
||||
std::vector<const char*> ImagesToRemove;
|
||||
bool listTextures = false;
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
if (argc >= 5) {
|
||||
int width = atoi(argv[3]);
|
||||
@@ -247,7 +282,7 @@ int main(int argc, const char** argv) {
|
||||
if(height >= 16 && height <= 1024)
|
||||
rw::dc::maxRasterHeight = height;
|
||||
}
|
||||
for (int i = 0; i < argc; i++) {
|
||||
for (int i = 5; i < argc; i++) {
|
||||
if (argv[i] != nullptr) {
|
||||
// Downsample Parameter
|
||||
if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-D") == 0) {
|
||||
@@ -271,6 +306,22 @@ int main(int argc, const char** argv) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--include-tex") == 0) {
|
||||
assert(i + 2 < argc);
|
||||
ImagesToAdd.emplace_back(argv[i+1], argv[i+2]);
|
||||
i += 2;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--delete-tex") == 0) {
|
||||
assert(i + 1 < argc);
|
||||
ImagesToRemove.emplace_back(argv[i+1]);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--list-tex") == 0) {
|
||||
listTextures = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,6 +349,31 @@ int main(int argc, const char** argv) {
|
||||
|
||||
RwStreamClose(stream, nil);
|
||||
|
||||
if (listTextures) {
|
||||
fprintf(stdout, "Incoming textures:\n");
|
||||
FORLIST(lnk, texDict->textures) {
|
||||
auto tex = rw::Texture::fromDict(lnk);
|
||||
fprintf(stdout, "texture: '%s'\n", tex->name);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto&& removedTextureName: ImagesToRemove) {
|
||||
auto removedTexture = texDict->find(removedTextureName);
|
||||
assert(removedTexture);
|
||||
texDict->remove(removedTexture);
|
||||
}
|
||||
for (auto&& extraTexture: ImagesToAdd) {
|
||||
InsertImage(texDict, extraTexture.first, extraTexture.second);
|
||||
}
|
||||
|
||||
if (listTextures) {
|
||||
fprintf(stdout, "Processing textures:\n");
|
||||
FORLIST(lnk, texDict->textures) {
|
||||
auto tex = rw::Texture::fromDict(lnk);
|
||||
fprintf(stdout, "texture: '%s'\n", tex->name);
|
||||
}
|
||||
}
|
||||
|
||||
auto streamOut = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, argv[2]);
|
||||
assert(streamOut && "failed to open output");
|
||||
|
||||
|
||||
@@ -3,100 +3,10 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>DCA3 - A port of RE3 for Dreamcast</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
background-color: #121212;
|
||||
color: #ffffff;
|
||||
}
|
||||
.navbar {
|
||||
background-color: #1f1f1f;
|
||||
}
|
||||
.hero {
|
||||
text-align: center;
|
||||
padding: 100px 20px;
|
||||
background-color: #333333;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.features {
|
||||
margin-top: 50px;
|
||||
}
|
||||
.footer {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
background-color: #1f1f1f;
|
||||
margin-top: 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
<title>DCA3 Redirect</title>
|
||||
<meta http-equiv="refresh" content="5;url=https://dca3.net">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">DCA3</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#features">Features</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#download">Download</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<div class="container">
|
||||
<div class="hero mt-4">
|
||||
<h1>DCA3</h1>
|
||||
<p>The first-ever port of Grand Theft Auto III to the SEGA Dreamcast, built from the REGTA reverse engineering project.</p>
|
||||
<a href="#download" class="btn btn-primary">Download Now</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features Section -->
|
||||
<div class="container features text-center">
|
||||
<h2 id="features" class="mb-4">Key Features</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<h3>Faithful Port</h3>
|
||||
<p>Experience GTA3 as it was meant to be, now on the Dreamcast with okay visuals and sluggish gameplay.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h3>Open Source</h3>
|
||||
<p>Built on the REGTA reverse engineering project, ensuring accuracy and community-driven development.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<h3>First Release</h3>
|
||||
<p>Celebrating our first release with not very much optimized performance and compatibility for Dreamcast hardware.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Download Section -->
|
||||
<div class="container text-center mt-5">
|
||||
<h2 id="download" class="mb-4">Download DCA3</h2>
|
||||
<p>Get started with the first release of and bring GTA3 to your Dreamcast. You'll need a PC copy of GTA3 to create your .cdi</p>
|
||||
<a href="#" class="btn btn-success btn-lg">Download Version 1.0</a>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="footer mt-4">
|
||||
<p>No rights reserved. Made with love for the Dreamcast community.</p>
|
||||
</footer>
|
||||
|
||||
<!-- Bootstrap JS Bundle -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<p>You will be redirected to <a href="https://dca3.net">dca3.net</a> in 5 seconds.</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -140,7 +140,7 @@ CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
|
||||
float blend = association->GetBlendAmount(weight);
|
||||
if(blend > 0.0f){
|
||||
auto kfAdt = sequence->GetDeltaTime(frameA);
|
||||
float t = (kfAdt - remainingTime)/kfAdt;
|
||||
float t = kfAdt == 0.0f ? 0.0f : (kfAdt - remainingTime)/kfAdt;
|
||||
if(sequence->type & CAnimBlendSequence::KF_TRANS){
|
||||
auto kfAt = sequence->GetTranslation(frameA);
|
||||
auto kfBt = sequence->GetTranslation(frameB);
|
||||
|
||||
@@ -3789,6 +3789,10 @@ cAudioManager::ProcessPedOneShots(cPedParams ¶ms)
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -6302,7 +6306,7 @@ cPedComments::Process()
|
||||
{
|
||||
case LOADING_STATUS_NOT_LOADED:
|
||||
SampleManager.LoadPedComment(sampleIndex);
|
||||
#ifdef GTA_PS2 // on PC ped comment is loaded at once
|
||||
#if defined(GTA_PS2) || defined(RW_DC) // on PC ped comment is loaded at once
|
||||
break;
|
||||
#endif
|
||||
case LOADING_STATUS_LOADED:
|
||||
|
||||
@@ -174,6 +174,10 @@ public:
|
||||
|
||||
void UpdateEffectsVolume(void);
|
||||
|
||||
#ifdef DC_SH4
|
||||
void UpdateChannelVolume(uint32 nChannel);
|
||||
#endif
|
||||
|
||||
void SetEffectsMasterVolume(uint8 nVolume);
|
||||
void SetMusicMasterVolume (uint8 nVolume);
|
||||
void SetEffectsFadeVolume (uint8 nVolume);
|
||||
|
||||
@@ -151,7 +151,6 @@ void aica_snd_sfx_freq_vol(int chn, int freq, int vol) {
|
||||
|
||||
cSampleManager SampleManager;
|
||||
bool8 _bSampmanInitialised = FALSE;
|
||||
bool _dcAudioInitialized = false;
|
||||
|
||||
uint32 BankStartOffset[MAX_SFX_BANKS];
|
||||
char SampleBankDescFilename[] = "sfx/sfx_all.dsc";
|
||||
@@ -166,8 +165,12 @@ struct sfx_bank {
|
||||
std::map<int, sfx_bank> sfx_banks;
|
||||
|
||||
int nPedSlotSfx[MAX_PEDSFX];
|
||||
uint32 nPedSlotSfxReqId[MAX_PEDSFX];
|
||||
uintptr_t nPedSlotSfxAddr[MAX_PEDSFX];
|
||||
uint8_t nCurrentPedSlot;
|
||||
file_t fdPedSfx;
|
||||
volatile uint32 nPedSfxReqReadId = 1;
|
||||
volatile uint32 nPedSfxReqNextId = 1;
|
||||
|
||||
struct WavHeader {
|
||||
// RIFF Header
|
||||
@@ -442,23 +445,30 @@ cSampleManager::Initialise(void)
|
||||
}
|
||||
});
|
||||
|
||||
nPedSfxReqNextId = 1;
|
||||
nPedSfxReqReadId = 1;
|
||||
for ( int32 i = 0; i < MAX_PEDSFX; i++ )
|
||||
{
|
||||
nPedSlotSfx[i] = -1;
|
||||
nPedSlotSfxReqId[i] = 0;
|
||||
nPedSlotSfxAddr[i] = snd_mem_malloc(PED_BLOCKSIZE_ADPCM);
|
||||
debugf("PedSlot %d buffer: %p\n", i, (void*)nPedSlotSfxAddr[i]);
|
||||
}
|
||||
|
||||
nCurrentPedSlot = 0;
|
||||
|
||||
_dcAudioInitialized = true;
|
||||
fdPedSfx = fs_open(SampleBankDataFilename, O_RDONLY);
|
||||
|
||||
assert(fdPedSfx >= 0);
|
||||
|
||||
_bSampmanInitialised = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::Terminate(void)
|
||||
{
|
||||
|
||||
fs_close(fdPedSfx);
|
||||
}
|
||||
|
||||
bool8 cSampleManager::CheckForAnAudioFileOnCD(void)
|
||||
@@ -474,7 +484,14 @@ char cSampleManager::GetCDAudioDriveLetter(void)
|
||||
void
|
||||
cSampleManager::UpdateEffectsVolume(void)
|
||||
{
|
||||
// TODO
|
||||
if(_bSampmanInitialised) {
|
||||
std::lock_guard<std::mutex> lk(channel_mtx);
|
||||
for (int i = 0; i < MAXCHANNELS+MAX2DCHANNELS; i++) {
|
||||
if (channels[i].ch != -1) {
|
||||
UpdateChannelVolume(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -637,7 +654,7 @@ cSampleManager::IsPedCommentLoaded(uint32 nComment)
|
||||
slot += ARRAY_SIZE(nPedSlotSfx);
|
||||
#endif
|
||||
if ( nComment == nPedSlotSfx[slot] )
|
||||
return LOADING_STATUS_LOADED;
|
||||
return nPedSlotSfxReqId[slot] <= nPedSfxReqReadId ? LOADING_STATUS_LOADED : LOADING_STATUS_LOADING;
|
||||
}
|
||||
|
||||
return LOADING_STATUS_NOT_LOADED;
|
||||
@@ -698,27 +715,28 @@ cSampleManager::LoadPedComment(uint32 nComment)
|
||||
|
||||
assert(m_aSamples[nComment].nByteSize < PED_BLOCKSIZE_ADPCM);
|
||||
|
||||
file_t fd = fs_open(SampleBankDataFilename, O_RDONLY);
|
||||
|
||||
assert(fd >= 0);
|
||||
debugf("Loading ped comment %d, offset: %d, size: %d\n", nComment, m_aSamples[nComment].nFileOffset, m_aSamples[nComment].nByteSize);
|
||||
fs_seek(fd, m_aSamples[nComment].nFileOffset, SEEK_SET);
|
||||
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);
|
||||
fs_seek(fdPedSfx, cmd->seek, SEEK_SET);
|
||||
|
||||
|
||||
// TODO: When we can dma directly to AICA, we can use this instead
|
||||
// fs_read(fd, SPU_BASE_U8 + nPedSlotSfxAddr[nCurrentPedSlot], sizeof(nPedSlotSfxAddr));
|
||||
// TODO: When we can dma directly to AICA, we can use this instead
|
||||
// fs_read(fdPedSfx, SPU_BASE_U8 + (uintptr_t)cmd->dest, cmd->size);
|
||||
|
||||
void* stagingBuffer = memalign(32, m_aSamples[nComment].nByteSize);
|
||||
assert(stagingBuffer != 0);
|
||||
debugf("Allocated %d bytes at %p\n", m_aSamples[nComment].nByteSize, stagingBuffer);
|
||||
int rs = fs_read(fd, stagingBuffer, m_aSamples[nComment].nByteSize);
|
||||
debugf("Read %d bytes, expected %d\n", rs, m_aSamples[nComment].nByteSize);
|
||||
assert(rs == m_aSamples[nComment].nByteSize);
|
||||
void* stagingBuffer = memalign(32, cmd->size);
|
||||
assert(stagingBuffer != 0);
|
||||
debugf("Allocated %d bytes at %p\n", cmd->size, stagingBuffer);
|
||||
int rs = fs_read(fdPedSfx, stagingBuffer, cmd->size);
|
||||
debugf("Read %d bytes, expected %d\n", rs, cmd->size);
|
||||
assert(rs == cmd->size);
|
||||
|
||||
fs_close(fd);
|
||||
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
|
||||
free(stagingBuffer);
|
||||
nPedSfxReqReadId = nPedSfxReqReadId + 1;
|
||||
});
|
||||
|
||||
spu_memload(nPedSlotSfxAddr[nCurrentPedSlot], stagingBuffer, m_aSamples[nComment].nByteSize);
|
||||
free(stagingBuffer);
|
||||
nPedSlotSfxReqId[nCurrentPedSlot] = ++nPedSfxReqNextId;
|
||||
|
||||
nPedSlotSfx[nCurrentPedSlot] = nComment;
|
||||
|
||||
if ( ++nCurrentPedSlot >= MAX_PEDSFX )
|
||||
@@ -839,9 +857,10 @@ cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void updateVol(uint32 nChannel) {
|
||||
void cSampleManager::UpdateChannelVolume(uint32 nChannel) {
|
||||
|
||||
auto newVol = channels[nChannel].emittingVol * channels[nChannel].attenuationVol / 255;
|
||||
newVol = m_nEffectsFadeVolume * newVol * m_nEffectsVolume >> 14;
|
||||
// newVol = 255;
|
||||
// printf("updateVol(nChannel: %d) vol: %d, newVol: %d\n", nChannel, channels[nChannel].vol, newVol);
|
||||
if (channels[nChannel].vol != newVol) {
|
||||
@@ -864,7 +883,7 @@ cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume)
|
||||
channels[nChannel].emittingVol = linearlize_volume(nVolume);// nVolume * 255 / MAX_VOLUME;
|
||||
channels[nChannel].attenuationVol = 255;
|
||||
|
||||
updateVol(nChannel);
|
||||
UpdateChannelVolume(nChannel);
|
||||
verbosef("SetChannelVolume(nChannel: %d) vol: %d\n", nChannel, nVolume);
|
||||
}
|
||||
|
||||
@@ -1120,7 +1139,8 @@ cSampleManager::StartStreamedFile(uint8 nFile, uint32 nPos, uint8 nStream)
|
||||
debugf("StartStreamedFile(%d, %d, %d)\n", nFile, nPos, nStream);
|
||||
uint32_t seek_aligned = 0;
|
||||
if (nPos) {
|
||||
uint32 seek_bytes = nPos * streams[nStream].rate / (streams[nStream].stereo ? 1000: 2000);
|
||||
uint64_t seek_bytes = (uint64_t)nPos * streams[nStream].rate / (streams[nStream].stereo ? 1000: 2000);
|
||||
assert(seek_bytes <= INT32_MAX);
|
||||
seek_aligned = seek_bytes & ~(streams[nStream].stereo ? (STREAM_STAGING_READ_SIZE_STEREO-1) : (STREAM_STAGING_READ_SIZE_MONO-1));
|
||||
}
|
||||
PreloadStreamedFile(nFile, nStream, seek_aligned);
|
||||
@@ -1152,7 +1172,9 @@ cSampleManager::GetStreamedFilePosition(uint8 nStream)
|
||||
ASSERT( nStream < MAX_STREAMS );
|
||||
int32 rv = 0;
|
||||
|
||||
return streams[nStream].played_samples * 1000 / streams[nStream].rate;
|
||||
int64_t rv64 = (int64_t)streams[nStream].played_samples * 1000 / streams[nStream].rate;
|
||||
assert(rv64 <= INT32_MAX);
|
||||
rv = (int32)rv64;
|
||||
// if(streams[nStream].fd >= 0) {
|
||||
// rv = fs_tell(streams[nStream].fd);
|
||||
// }
|
||||
@@ -1167,6 +1189,7 @@ cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffect
|
||||
if (nVolume > MAX_VOLUME)
|
||||
nVolume = MAX_VOLUME;
|
||||
nVolume = linearlize_volume(nVolume); //nVolume * 255 / MAX_VOLUME;
|
||||
nVolume = m_nMusicFadeVolume * nVolume * m_nMusicVolume >> 14;
|
||||
if (streams[nStream].vol != nVolume || streams[nStream].nPan != nPan) {
|
||||
streams[nStream].vol = nVolume;
|
||||
streams[nStream].nPan = nPan;
|
||||
@@ -1195,7 +1218,10 @@ cSampleManager::GetStreamedFileLength(uint8 nFile)
|
||||
WavHeader hdr;
|
||||
assert(fs_read(fd, &hdr, sizeof(hdr)) == sizeof(hdr));
|
||||
|
||||
rv = hdr.dataSize * 2000 / hdr.numOfChan / hdr.samplesPerSec;
|
||||
uint64_t rv64 = (uint64_t)hdr.dataSize * 2000 / hdr.numOfChan / hdr.samplesPerSec;
|
||||
|
||||
assert(rv64 <= INT32_MAX);
|
||||
rv = (int32)rv64;
|
||||
|
||||
fs_close(fd);
|
||||
|
||||
@@ -1275,9 +1301,17 @@ void cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)
|
||||
if (nVolume > MAX_VOLUME)
|
||||
nVolume = MAX_VOLUME;
|
||||
|
||||
// reduce channel volume when JB.MP3 or S4_BDBD.MP3 playing
|
||||
if ( MusicManager.GetMusicMode() == MUSICMODE_CUTSCENE
|
||||
&& MusicManager.GetNextTrack() != STREAMED_SOUND_NEWS_INTRO
|
||||
&& MusicManager.GetNextTrack() != STREAMED_SOUND_CUTSCENE_SAL4_BDBD )
|
||||
{
|
||||
nVolume /= 4;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lk(channel_mtx);
|
||||
channels[nChannel].emittingVol = linearlize_volume(nVolume); // nVolume * 255 / MAX_VOLUME;
|
||||
updateVol(nChannel);
|
||||
UpdateChannelVolume(nChannel);
|
||||
}
|
||||
|
||||
float calculatePan(float x, float z) {
|
||||
@@ -1322,7 +1356,7 @@ void cSampleManager::SetChannel3DPosition (uint32 nChannel, float fX, float
|
||||
channels[nChannel].fY = fY;
|
||||
channels[nChannel].fZ = fZ;
|
||||
channels[nChannel].attenuationVol = calculateAttenuation(channels[nChannel].fX, channels[nChannel].fY, channels[nChannel].fZ, channels[nChannel].distMin, channels[nChannel].distMax) * 255;
|
||||
updateVol(nChannel);
|
||||
UpdateChannelVolume(nChannel);
|
||||
}
|
||||
|
||||
SetChannelPan(nChannel, calculatePan(-fX, fZ) * 63 + 64);
|
||||
@@ -1335,7 +1369,7 @@ void cSampleManager::SetChannel3DDistances (uint32 nChannel, float fMax, floa
|
||||
channels[nChannel].distMin = fMin;
|
||||
channels[nChannel].distMax = fMax;
|
||||
channels[nChannel].attenuationVol = calculateAttenuation(channels[nChannel].fX, channels[nChannel].fY, channels[nChannel].fZ, channels[nChannel].distMin, channels[nChannel].distMax) * 255;
|
||||
updateVol(nChannel);
|
||||
UpdateChannelVolume(nChannel);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1721,8 +1721,8 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
|
||||
return 0;
|
||||
int attempts;
|
||||
int model = -1;
|
||||
int index = CGeneral::GetRandomNumberInRange(0, 50);
|
||||
for (attempts = 0; attempts < 50; attempts++) {
|
||||
int index = CGeneral::GetRandomNumberInRange(0, MAXVEHICLESLOADED);
|
||||
for (attempts = 0; attempts < MAXVEHICLESLOADED; attempts++) {
|
||||
if (model != -1)
|
||||
break;
|
||||
model = CStreaming::ms_vehiclesLoaded[index];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
|
||||
#define CDSTREAM_SECTOR_SIZE 2048
|
||||
|
||||
@@ -43,7 +44,14 @@ char *CdStreamGetImageName(int32 cd);
|
||||
void CdStreamRemoveImages(void);
|
||||
int32 CdStreamGetNumImages(void);
|
||||
|
||||
void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek);
|
||||
struct AudioReadCmd {
|
||||
void* dest;
|
||||
int fd;
|
||||
size_t size;
|
||||
size_t seek;
|
||||
std::function<void(AudioReadCmd*)> callback;
|
||||
};
|
||||
void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek, std::function<void(AudioReadCmd*)> callback = nullptr);
|
||||
void CdStreamDiscardAudioRead(int fd);
|
||||
|
||||
#ifdef FLUSHABLE_STREAMING
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
#include "CdStream.h"
|
||||
#include "rwcore.h"
|
||||
#include "MemoryMgr.h"
|
||||
struct AudioReadCmd {
|
||||
void* dest;
|
||||
int fd;
|
||||
size_t size;
|
||||
size_t seek;
|
||||
};
|
||||
|
||||
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
|
||||
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
|
||||
@@ -489,8 +483,16 @@ std::vector<AudioReadCmd> pendingAudioReads;
|
||||
std::mutex pendingAudioReadsMutex;
|
||||
#endif
|
||||
// Will replace a previous read request for the same file descriptor
|
||||
void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek) {
|
||||
void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek, std::function<void(AudioReadCmd*)> callback) {
|
||||
AudioReadCmd cmd = { pBuffer, fd, bytes, seek};
|
||||
if (!callback) {
|
||||
cmd.callback = [](AudioReadCmd* cmd){
|
||||
lseek(cmd->fd, cmd->seek, SEEK_SET);
|
||||
read(cmd->fd, cmd->dest, cmd->size);
|
||||
};
|
||||
} else {
|
||||
cmd.callback = callback;
|
||||
}
|
||||
{
|
||||
#if !defined(DC_SH4)
|
||||
std::lock_guard<std::mutex> lock(pendingAudioReadsMutex);
|
||||
@@ -514,6 +516,7 @@ void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek) {
|
||||
sem_post(gCdStreamSema);
|
||||
}
|
||||
|
||||
|
||||
void CdStreamDiscardAudioRead(int fd) {
|
||||
#if !defined(DC_SH4)
|
||||
std::lock_guard<std::mutex> lock(pendingAudioReadsMutex);
|
||||
@@ -564,8 +567,7 @@ int read_loop(int fd, void* pBuffer, size_t bytes) {
|
||||
total_read += read_bytes;
|
||||
auto cmd = CdStreamNextAudioRead();
|
||||
while (cmd.fd != -1) {
|
||||
lseek(cmd.fd, cmd.seek, SEEK_SET);
|
||||
read(cmd.fd, cmd.dest, cmd.size);
|
||||
cmd.callback(&cmd);
|
||||
cmd = CdStreamNextAudioRead();
|
||||
}
|
||||
}
|
||||
@@ -581,8 +583,7 @@ void *CdStreamThread(void *param)
|
||||
|
||||
auto cmd = CdStreamNextAudioRead();
|
||||
while (cmd.fd != -1) {
|
||||
lseek(cmd.fd, cmd.seek, SEEK_SET);
|
||||
read(cmd.fd, cmd.dest, cmd.size);
|
||||
cmd.callback(&cmd);
|
||||
cmd = CdStreamNextAudioRead();
|
||||
}
|
||||
|
||||
|
||||
@@ -2785,22 +2785,22 @@ bool CPad::WeaponJustDown(void)
|
||||
case 0: //Xbox Mode
|
||||
if (CPad::GetPad(0)->IsDualAnalog)
|
||||
{
|
||||
if (NewState.RightTrigger > 128)
|
||||
if (NewState.RightTrigger > 128 && !(OldState.RightTrigger > 128))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NewState.RightTrigger > 128)
|
||||
if (NewState.RightTrigger > 128 && !(OldState.RightTrigger > 128))
|
||||
return true;
|
||||
}
|
||||
case 1: //PS2 Mode
|
||||
if (CPad::GetPad(0)->IsDualAnalog)
|
||||
{
|
||||
return NewState.B;
|
||||
return NewState.B && !OldState.B;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NewState.B;
|
||||
return NewState.B && !OldState.B;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -379,7 +379,7 @@ enum Config {
|
||||
# define CUSTOM_FRONTEND_OPTIONS
|
||||
|
||||
# ifdef CUSTOM_FRONTEND_OPTIONS
|
||||
# define MENU_MAP // VC-like menu map. Won't appear if you don't have our menu.txd
|
||||
# define MENU_MAP // Enabled on Dca3 now, but could use some controller mapping**
|
||||
# define GRAPHICS_MENU_OPTIONS // otherwise Display settings will be scrollable
|
||||
# define NO_ISLAND_LOADING // disable loadscreen between islands via loading all island data at once, consumes more memory and CPU
|
||||
# define CUTSCENE_BORDERS_SWITCH
|
||||
|
||||
@@ -83,6 +83,11 @@ CEntity::~CEntity(void)
|
||||
ResolveReferences();
|
||||
}
|
||||
|
||||
bool
|
||||
CEntity::IsFence(void) {
|
||||
return IsObject() && ::IsFence(static_cast<CObject *>(this)->GetModelIndex());
|
||||
}
|
||||
|
||||
void
|
||||
CEntity::SetModelIndex(uint32 id)
|
||||
{
|
||||
|
||||
@@ -131,6 +131,7 @@ public:
|
||||
bool IsPed(void) { return m_type == ENTITY_TYPE_PED; }
|
||||
bool IsObject(void) { return m_type == ENTITY_TYPE_OBJECT; }
|
||||
bool IsDummy(void) { return m_type == ENTITY_TYPE_DUMMY; }
|
||||
bool IsFence(void);
|
||||
|
||||
RpAtomic *GetAtomic(void) {
|
||||
assert(RwObjectGetType(m_rwObject) == rpATOMIC);
|
||||
|
||||
@@ -59,7 +59,7 @@ CPhysical::CPhysical(void)
|
||||
bInfiniteMass = false;
|
||||
bIsInWater = false;
|
||||
bHitByTrain = false;
|
||||
bSkipLineCol = false;
|
||||
bSkipLineCol = IsFence();
|
||||
|
||||
m_fDistanceTravelled = 0.0f;
|
||||
m_treadable[PATH_CAR] = nil;
|
||||
@@ -1461,6 +1461,10 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
|
||||
skipCollision = false;
|
||||
altcollision = false;
|
||||
|
||||
if(A->IsFence() && B->IsFence()) {
|
||||
skipCollision = true;
|
||||
A->bSkipLineCol = true;
|
||||
}
|
||||
if(B->IsBuilding())
|
||||
skipCollision = false;
|
||||
else if(IsStreetLight(A->GetModelIndex()) &&
|
||||
@@ -1922,12 +1926,12 @@ CPhysical::ProcessCollision(void)
|
||||
n = NUMSTEPS(0.09f);
|
||||
step = savedTimeStep / n;
|
||||
}
|
||||
}else if(responsecase == COLLRESPONSE_SMALLBOX || responsecase == COLLRESPONSE_FENCEPART){
|
||||
}else if(responsecase == COLLRESPONSE_SMALLBOX){
|
||||
if(distSq >= sq(0.15f)){
|
||||
n = NUMSTEPS(0.15f);
|
||||
step = savedTimeStep / n;
|
||||
}
|
||||
}else{
|
||||
}else if(responsecase != COLLRESPONSE_FENCEPART){
|
||||
if(distSq >= sq(0.3f)){
|
||||
n = NUMSTEPS(0.3f);
|
||||
step = savedTimeStep / n;
|
||||
|
||||
@@ -282,7 +282,7 @@ CMatrix::SetRotate(float xAngle, float yAngle, float zAngle)
|
||||
void
|
||||
CMatrix::RotateX(float x)
|
||||
{
|
||||
#ifdef DC_SH4
|
||||
#if 0 && defined(DC_SH4) // this is bugged and does not yield correct results
|
||||
mat_load(reinterpret_cast<matrix_t *>(this));
|
||||
mat_rotate_x(x);
|
||||
mat_store(reinterpret_cast<matrix_t *>(this));
|
||||
@@ -312,7 +312,7 @@ CMatrix::RotateX(float x)
|
||||
void
|
||||
CMatrix::RotateY(float y)
|
||||
{
|
||||
#ifdef DC_SH4
|
||||
#if 0 && defined(DC_SH4) // this is bugged and does not yield correct results
|
||||
mat_load(reinterpret_cast<matrix_t *>(this));
|
||||
mat_rotate_y(y);
|
||||
mat_store(reinterpret_cast<matrix_t *>(this));
|
||||
@@ -342,7 +342,7 @@ CMatrix::RotateY(float y)
|
||||
void
|
||||
CMatrix::RotateZ(float z)
|
||||
{
|
||||
#ifdef DC_SH4
|
||||
#if 0 && defined(DC_SH4) // this is bugged and does not yield correct results
|
||||
mat_load(reinterpret_cast<matrix_t *>(this));
|
||||
mat_rotate_z(z);
|
||||
mat_store(reinterpret_cast<matrix_t *>(this));
|
||||
@@ -372,7 +372,7 @@ CMatrix::RotateZ(float z)
|
||||
void
|
||||
CMatrix::Rotate(float x, float y, float z)
|
||||
{
|
||||
#ifdef DC_SH4
|
||||
#if 0 && defined(DC_SH4) // this is bugged and does not yield correct results
|
||||
mat_load(reinterpret_cast<matrix_t *>(this));
|
||||
mat_rotate(x, y, z);
|
||||
mat_store(reinterpret_cast<matrix_t *>(this));
|
||||
@@ -404,6 +404,20 @@ CMatrix::Rotate(float x, float y, float z)
|
||||
float z2 = sZ * sY - (cZ * sX) * cY;
|
||||
float z3 = cX * cY;
|
||||
|
||||
#if !defined(DC_TEXCONV) && !defined(DC_SIM)
|
||||
this->rx = fipr(x1, y1, z1, 0, rx, ry, rz, 0);
|
||||
this->ry = fipr(x2, y2, z2, 0, rx, ry, rz, 0);
|
||||
this->rz = fipr(x3, y3, z3, 0, rx, ry, rz, 0);
|
||||
this->fx = fipr(x1, y1, z1, 0, ux, uy, uz, 0);
|
||||
this->fy = fipr(x2, y2, z2, 0, ux, uy, uz, 0);
|
||||
this->fz = fipr(x3, y3, z3, 0, ux, uy, uz, 0);
|
||||
this->ux = fipr(x1, y1, z1, 0, ax, ay, az, 0);
|
||||
this->uy = fipr(x2, y2, z2, 0, ax, ay, az, 0);
|
||||
this->uz = fipr(x3, y3, z3, 0, ax, ay, az, 0);
|
||||
this->px = fipr(x1, y1, z1, 0, px, py, pz, 0);
|
||||
this->py = fipr(x2, y2, z2, 0, px, py, pz, 0);
|
||||
this->pz = fipr(x3, y3, z3, 0, px, py, pz, 0);
|
||||
#else
|
||||
this->rx = x1 * rx + y1 * ry + z1 * rz;
|
||||
this->ry = x2 * rx + y2 * ry + z2 * rz;
|
||||
this->rz = x3 * rx + y3 * ry + z3 * rz;
|
||||
@@ -416,6 +430,7 @@ CMatrix::Rotate(float x, float y, float z)
|
||||
this->px = x1 * px + y1 * py + z1 * pz;
|
||||
this->py = x2 * px + y2 * py + z2 * pz;
|
||||
this->pz = x3 * px + y3 * py + z3 * pz;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1479,7 +1479,8 @@ CWaterLevel::AllocateBoatWakeArray()
|
||||
apGeomArray[geom] = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP
|
||||
| rpGEOMETRYPRELIT
|
||||
| rpGEOMETRYMODULATEMATERIALCOLOR
|
||||
| rpGEOMETRYTEXTURED);
|
||||
| rpGEOMETRYTEXTURED
|
||||
| rw::Geometry::HAS_TRIANGLES/* RW_DC specific */);
|
||||
ASSERT(apGeomArray[geom] != nil);
|
||||
|
||||
RpTriangle *geomTriangles = RpGeometryGetTriangles(apGeomArray[geom]);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# include <dc/sound/sound.h>
|
||||
# endif
|
||||
|
||||
extern bool _dcAudioInitialized;
|
||||
extern bool _bSampmanInitialised;
|
||||
|
||||
// ====== STATIC METHODS =====
|
||||
|
||||
@@ -86,7 +86,7 @@ void VmuProfiler::run() {
|
||||
|
||||
#ifdef DC_SH4
|
||||
if(auto *dev = maple_enum_type(0, MAPLE_FUNC_MEMCARD);
|
||||
dev && _dcAudioInitialized && updated_)
|
||||
dev && _bSampmanInitialised && updated_)
|
||||
{
|
||||
pvr_stats_t pvrStats; pvr_get_stats(&pvrStats);
|
||||
uint32_t sramStats = snd_mem_available();
|
||||
|
||||
30
vendor/librw/src/dc/rwdc.cpp
vendored
@@ -305,6 +305,8 @@ void rw_mat_load_4x4(rw::Matrix* mtx) {
|
||||
#define mat_identity(a)
|
||||
#define pvr_fog_table_color(a,r,g,b)
|
||||
#define pvr_fog_table_linear(s,e)
|
||||
#define pvr_fog_table_exp(d)
|
||||
#define pvr_fog_table_custom(d)
|
||||
#endif
|
||||
|
||||
#define mat_trans_single3_nomod(x_, y_, z_, x2, y2, z2) do { \
|
||||
@@ -663,7 +665,10 @@ void malloc_stats() { }
|
||||
#define UNIMPL_LOGV(...)
|
||||
#endif
|
||||
|
||||
Camera* rwdcCam;
|
||||
|
||||
void beginUpdate(Camera* cam) {
|
||||
rwdcCam = cam;
|
||||
float view[16], proj[16];
|
||||
|
||||
// View Matrix
|
||||
@@ -1098,6 +1103,7 @@ static bool doAlphaTest;
|
||||
|
||||
static uint8_t fogFuncPvr = PVR_FOG_DISABLE;
|
||||
static uint32_t fogColor = 0;
|
||||
static float fogStart = 0.0f;
|
||||
static uint32 cullModePvr;
|
||||
|
||||
static inline unsigned pvrCullMode(uint32_t cullMode) {
|
||||
@@ -1198,8 +1204,9 @@ setRenderState(int32 state, void *pvalue)
|
||||
fogFuncPvr = value ? PVR_FOG_TABLE : PVR_FOG_DISABLE;
|
||||
break;
|
||||
case FOGCOLOR:
|
||||
#if !defined(DC_TEXCONV)
|
||||
// Set fog color when state changes
|
||||
if(fogColor != value) {
|
||||
if(fogColor != value || fogStart != RwCameraGetFogDistance(rwdcCam)) {
|
||||
fogColor = value;
|
||||
RGBA c;
|
||||
c.red = value;
|
||||
@@ -1207,9 +1214,22 @@ setRenderState(int32 state, void *pvalue)
|
||||
c.blue = value>>16;
|
||||
c.alpha = value>>24;
|
||||
pvr_fog_table_color(c.alpha / 255.0f, c.red / 255.0f, c.green / 255.0f, c.blue / 255.0f);
|
||||
pvr_fog_table_linear(50.0f, 450.0f);
|
||||
|
||||
fogStart = RwCameraGetFogDistance(rwdcCam);
|
||||
float fogEnd = RwCameraGetFarClipPlane(rwdcCam);
|
||||
float fogIntensity[129];
|
||||
uint8_t idx = 0;
|
||||
float startIntensity = (-fogStart) / (fogEnd - fogStart); //interpolate between start and end to get initial intensity
|
||||
float step = (1.0f - startIntensity) / 129; // we have 129 entries, create a step such that start + (step*129) = 1.0
|
||||
for(int i = 128; i >= 0; i--) {
|
||||
fogIntensity[i] = startIntensity + (idx++ * step);
|
||||
}
|
||||
pvr_fog_far_depth(fogEnd);
|
||||
pvr_fog_table_custom(fogIntensity);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
// case CULLMODE:
|
||||
// if(rwStateCache.cullmode != value){
|
||||
// rwStateCache.cullmode = value;
|
||||
@@ -3294,6 +3314,8 @@ void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
|
||||
|
||||
for (int16_t n = 0; n < numMeshes; n++) {
|
||||
bool doBlend = meshes[n].material->color.alpha != 255; // TODO: check all vertexes for alpha?
|
||||
bool doBlendMaterial = doBlend;
|
||||
|
||||
bool textured = geo->numTexCoordSets && meshes[n].material->texture;
|
||||
if (textured) {
|
||||
doBlend |= Raster::formatHasAlpha(meshes[n].material->texture->raster->format);
|
||||
@@ -3343,7 +3365,7 @@ void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
|
||||
pvr_poly_cxt_t cxt;
|
||||
int pvrList;
|
||||
if (doBlend || isMatFX) {
|
||||
if (doAlphaTest) {
|
||||
if (doAlphaTest && !doBlendMaterial) {
|
||||
pvrList = PVR_LIST_PT_POLY;
|
||||
} else {
|
||||
pvrList = PVR_LIST_TR_POLY;
|
||||
@@ -3709,7 +3731,7 @@ void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
|
||||
};
|
||||
|
||||
if (doBlend || isMatFX) {
|
||||
if (doAlphaTest) {
|
||||
if (doAlphaTest && !doBlendMaterial) {
|
||||
ptCallbacks.emplace_back(std::move(renderCB));
|
||||
} else {
|
||||
blendCallbacks.emplace_back(std::move(renderCB));
|
||||
|
||||