Compare commits

..

1 Commits

Author SHA1 Message Date
Josh Pearson
36796dd7db Reduce rain streaks and drops to minimize PVR fillrate hit
Can improve performance by up to 10 FPS in areas when raining
2024-12-30 15:54:43 -07:00
10 changed files with 141 additions and 86 deletions

View File

@@ -3,10 +3,100 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DCA3 Redirect</title>
<meta http-equiv="refresh" content="5;url=https://dca3.net">
<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>
</head>
<body>
<p>You will be redirected to <a href="https://dca3.net">dca3.net</a> in 5 seconds.</p>
<!-- 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>
</body>
</html>
</html>

View File

@@ -6302,7 +6302,7 @@ cPedComments::Process()
{
case LOADING_STATUS_NOT_LOADED:
SampleManager.LoadPedComment(sampleIndex);
#if defined(GTA_PS2) || defined(RW_DC) // on PC ped comment is loaded at once
#ifdef GTA_PS2 // on PC ped comment is loaded at once
break;
#endif
case LOADING_STATUS_LOADED:

View File

@@ -166,12 +166,8 @@ 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
@@ -446,22 +442,15 @@ 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;
fdPedSfx = fs_open(SampleBankDataFilename, O_RDONLY);
assert(fdPedSfx >= 0);
_dcAudioInitialized = true;
return TRUE;
}
@@ -469,7 +458,7 @@ cSampleManager::Initialise(void)
void
cSampleManager::Terminate(void)
{
fs_close(fdPedSfx);
}
bool8 cSampleManager::CheckForAnAudioFileOnCD(void)
@@ -648,7 +637,7 @@ cSampleManager::IsPedCommentLoaded(uint32 nComment)
slot += ARRAY_SIZE(nPedSlotSfx);
#endif
if ( nComment == nPedSlotSfx[slot] )
return nPedSlotSfxReqId[slot] <= nPedSfxReqReadId ? LOADING_STATUS_LOADED : LOADING_STATUS_LOADING;
return LOADING_STATUS_LOADED;
}
return LOADING_STATUS_NOT_LOADED;
@@ -709,28 +698,27 @@ cSampleManager::LoadPedComment(uint32 nComment)
assert(m_aSamples[nComment].nByteSize < PED_BLOCKSIZE_ADPCM);
CdStreamQueueAudioRead(nComment, (void*)nPedSlotSfxAddr[nCurrentPedSlot], m_aSamples[nComment].nByteSize, m_aSamples[nComment].nFileOffset, [](AudioReadCmd* cmd) {
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);
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);
// 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);
// TODO: When we can dma directly to AICA, we can use this instead
// fs_read(fd, SPU_BASE_U8 + nPedSlotSfxAddr[nCurrentPedSlot], sizeof(nPedSlotSfxAddr));
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);
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);
spu_memload((uintptr_t)cmd->dest, stagingBuffer, cmd->size);
free(stagingBuffer);
nPedSfxReqReadId = nPedSfxReqReadId + 1;
});
fs_close(fd);
nPedSlotSfxReqId[nCurrentPedSlot] = ++nPedSfxReqNextId;
spu_memload(nPedSlotSfxAddr[nCurrentPedSlot], stagingBuffer, m_aSamples[nComment].nByteSize);
free(stagingBuffer);
nPedSlotSfx[nCurrentPedSlot] = nComment;
if ( ++nCurrentPedSlot >= MAX_PEDSFX )

View File

@@ -1,5 +1,4 @@
#pragma once
#include <functional>
#define CDSTREAM_SECTOR_SIZE 2048
@@ -44,14 +43,7 @@ char *CdStreamGetImageName(int32 cd);
void CdStreamRemoveImages(void);
int32 CdStreamGetNumImages(void);
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 CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek);
void CdStreamDiscardAudioRead(int fd);
#ifdef FLUSHABLE_STREAMING

View File

@@ -26,6 +26,12 @@
#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__)
@@ -483,16 +489,8 @@ 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, std::function<void(AudioReadCmd*)> callback) {
void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek) {
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);
@@ -516,7 +514,6 @@ void CdStreamQueueAudioRead(int fd, void* pBuffer, size_t bytes, size_t seek, st
sem_post(gCdStreamSema);
}
void CdStreamDiscardAudioRead(int fd) {
#if !defined(DC_SH4)
std::lock_guard<std::mutex> lock(pendingAudioReadsMutex);
@@ -567,7 +564,8 @@ int read_loop(int fd, void* pBuffer, size_t bytes) {
total_read += read_bytes;
auto cmd = CdStreamNextAudioRead();
while (cmd.fd != -1) {
cmd.callback(&cmd);
lseek(cmd.fd, cmd.seek, SEEK_SET);
read(cmd.fd, cmd.dest, cmd.size);
cmd = CdStreamNextAudioRead();
}
}
@@ -583,7 +581,8 @@ void *CdStreamThread(void *param)
auto cmd = CdStreamNextAudioRead();
while (cmd.fd != -1) {
cmd.callback(&cmd);
lseek(cmd.fd, cmd.seek, SEEK_SET);
read(cmd.fd, cmd.dest, cmd.size);
cmd = CdStreamNextAudioRead();
}

View File

@@ -282,7 +282,7 @@ CMatrix::SetRotate(float xAngle, float yAngle, float zAngle)
void
CMatrix::RotateX(float x)
{
#if 0 && defined(DC_SH4) // this is bugged and does not yield correct results
#ifdef DC_SH4
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)
{
#if 0 && defined(DC_SH4) // this is bugged and does not yield correct results
#ifdef DC_SH4
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)
{
#if 0 && defined(DC_SH4) // this is bugged and does not yield correct results
#ifdef DC_SH4
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)
{
#if 0 && defined(DC_SH4) // this is bugged and does not yield correct results
#ifdef DC_SH4
mat_load(reinterpret_cast<matrix_t *>(this));
mat_rotate(x, y, z);
mat_store(reinterpret_cast<matrix_t *>(this));
@@ -404,20 +404,6 @@ 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;
@@ -430,7 +416,6 @@ 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
}

View File

@@ -1479,8 +1479,7 @@ CWaterLevel::AllocateBoatWakeArray()
apGeomArray[geom] = RpGeometryCreate(9*9, 8*8*2, rpGEOMETRYTRISTRIP
| rpGEOMETRYPRELIT
| rpGEOMETRYMODULATEMATERIALCOLOR
| rpGEOMETRYTEXTURED
| rw::Geometry::HAS_TRIANGLES/* RW_DC specific */);
| rpGEOMETRYTEXTURED);
ASSERT(apGeomArray[geom] != nil);
RpTriangle *geomTriangles = RpGeometryGetTriangles(apGeomArray[geom]);

View File

@@ -301,7 +301,11 @@ void CWeather::AddRain()
float screen_width = SCREEN_WIDTH;
float screen_height = SCREEN_HEIGHT;
int cur_frame = (int)(3 * Rain) & 3;
#if defined(DC_SH4)
int num_drops = (int)(1 * Rain) + 2;
#elif
int num_drops = (int)(2 * Rain) + 2;
#endif
static int STATIC_RAIN_ANGLE = -45;
static int count = 1500;
static int add_angle = 1;

View File

@@ -58,7 +58,7 @@ public:
};
enum {
NUM_RAIN_STREAKS = 35
NUM_RAIN_STREAKS = 10
};
struct tRainStreak

View File

@@ -3294,8 +3294,6 @@ 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);
@@ -3345,7 +3343,7 @@ void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
pvr_poly_cxt_t cxt;
int pvrList;
if (doBlend || isMatFX) {
if (doAlphaTest && !doBlendMaterial) {
if (doAlphaTest) {
pvrList = PVR_LIST_PT_POLY;
} else {
pvrList = PVR_LIST_TR_POLY;
@@ -3711,7 +3709,7 @@ void defaultRenderCB(ObjPipeline *pipe, Atomic *atomic) {
};
if (doBlend || isMatFX) {
if (doAlphaTest && !doBlendMaterial) {
if (doAlphaTest) {
ptCallbacks.emplace_back(std::move(renderCB));
} else {
blendCallbacks.emplace_back(std::move(renderCB));
@@ -3887,19 +3885,19 @@ imageFindRasterFormat(Image *img, int32 type,
;
if(downsampleMode >= HALF) {
if(height / 2 >= 64) {
if(height / 2 >= 16) {
height /= 2;
}
if(width / 2 >= 64) {
if(width / 2 >= 16) {
width /= 2;
}
}
if(downsampleMode >= QUARTER) {
if(height / 2 >= 32) {
if(height / 2 >= 16) {
height /= 2;
}
if(width / 2 >= 32) {
if(width / 2 >= 16) {
width /= 2;
}
}