Now the TXD.img file is being created correctly, and the textures are reduced to half their size, saving a lot of memory and making the game run more smoothly. The game no longer crashes and it looks very good. That said, I still couldn’t increase the frame rate—it stays between 8 and 15 FPS, but usually runs around 8

This commit is contained in:
Dante Leoncini 2026-05-06 03:22:18 -03:00
parent 39c75bb8c5
commit 6d9929b7ce
4 changed files with 189 additions and 107 deletions

View file

@ -270,7 +270,7 @@ CStreaming::Init2(void)
void void
CStreaming::Init(void) CStreaming::Init(void)
{ {
/*#ifdef USE_TXD_CDIMAGE #ifdef USE_TXD_CDIMAGE
int txdHandle = CFileMgr::OpenFile("MODELS\\TXD.IMG", "r"); int txdHandle = CFileMgr::OpenFile("MODELS\\TXD.IMG", "r");
if (txdHandle) if (txdHandle)
CFileMgr::CloseFile(txdHandle); CFileMgr::CloseFile(txdHandle);
@ -285,9 +285,9 @@ CStreaming::Init(void)
CStreaming::Init2(); CStreaming::Init2();
} }
} }
#else*/ #else
CStreaming::Init2(); CStreaming::Init2();
//#endif #endif
} }
void void

View file

@ -93,36 +93,106 @@ static int clamp(int size, int targetSize)
return size; return size;
} }
static void downscaleTexture(RwTexture *texture) void debugRaster(RwRaster *r){
{ if(!r){
RwRaster *oldRaster = RwTextureGetRaster(texture); debug("Raster NULL");
if (oldRaster == nil) return;
return; }
extern bool moreVram; debug("Raster: %dx%d | depth: %d | format: 0x%X | stride: %d | platform: %d | pixels: %p",
int targetSize = moreVram ? 64 : 32; r->width,
r->height,
r->depth,
r->format,
r->stride,
r->platform,
r->pixels);
}
int oldWidth = RwRasterGetWidth(oldRaster); static void downscaleTexture(RwTexture *texture){
int oldHeight = RwRasterGetHeight(oldRaster); #ifdef RW_GLES1
if (oldWidth <= targetSize && oldHeight <= targetSize) return; if(texture == nil)
return;
int newWidth = clamp(oldWidth, targetSize); RwRaster *oldRaster = RwTextureGetRaster(texture);
int newHeight = clamp(oldHeight, targetSize); if(oldRaster == nil)
if (newWidth == oldWidth && newHeight == oldHeight) return; return;
RwImage *image = oldRaster->toImage(); int oldWidth = RwRasterGetWidth(oldRaster);
if (image == nil) return; int oldHeight = RwRasterGetHeight(oldRaster);
RwImage *resized = resizeImage(image, newWidth, newHeight); // dividir a la mitad, mínimo 16x16
RwImageDestroy(image); int newWidth = oldWidth > 16 ? oldWidth / 2 : oldWidth;
if (resized == nil) return; int newHeight = oldHeight > 16 ? oldHeight / 2 : oldHeight;
RwRaster *newRaster = rw::Raster::createFromImage(resized); // si ya es suficientemente chica, no hacer nada
RwImageDestroy(resized); if(newWidth == oldWidth && newHeight == oldHeight)
if (newRaster == nil) return; return;
RwTextureSetRaster(texture, newRaster); // toImage() funciona porque el backingStore está populado
RwRasterDestroy(oldRaster); RwImage *image = oldRaster->toImage();
if(image == nil){
debug("downscaleTexture: toImage FAILED for %dx%d", oldWidth, oldHeight);
return;
}
RwImage *resized = resizeImage(image, newWidth, newHeight);
RwImageDestroy(image);
if(resized == nil){
debug("downscaleTexture: resizeImage FAILED");
return;
}
// crear nuevo raster en formato compatible con GLES1
int32 w, h, d, f;
rw::Raster::imageFindRasterFormat(resized, rw::Raster::TEXTURE, &w, &h, &d, &f);
RwRaster *newRaster = rw::Raster::create(w, h, d, f | rw::Raster::TEXTURE, rw::PLATFORM_GLES1);
if(newRaster == nil){
debug("downscaleTexture: raster create FAILED");
RwImageDestroy(resized);
return;
}
if(newRaster->setFromImage(resized) == nil){
debug("downscaleTexture: setFromImage FAILED");
RwRasterDestroy(newRaster);
RwImageDestroy(resized);
return;
}
RwImageDestroy(resized);
RwTextureSetRaster(texture, newRaster);
RwRasterDestroy(oldRaster);
#else
RwRaster *oldRaster = RwTextureGetRaster(texture);
if (oldRaster == nil)
return;
extern bool moreVram;
int targetSize = moreVram ? 64 : 32;
int oldWidth = RwRasterGetWidth(oldRaster);
int oldHeight = RwRasterGetHeight(oldRaster);
if (oldWidth <= targetSize && oldHeight <= targetSize) return;
int newWidth = clamp(oldWidth, targetSize);
int newHeight = clamp(oldHeight, targetSize);
if (newWidth == oldWidth && newHeight == oldHeight) return;
RwImage *image = oldRaster->toImage();
if (image == nil) return;
RwImage *resized = resizeImage(image, newWidth, newHeight);
RwImageDestroy(image);
if (resized == nil) return;
RwRaster *newRaster = rw::Raster::createFromImage(resized);
RwImageDestroy(resized);
if (newRaster == nil) return;
RwTextureSetRaster(texture, newRaster);
RwRasterDestroy(oldRaster);
#endif
} }
#endif #endif

View file

@ -308,9 +308,7 @@ flushGlRenderState(void)
void void setAlphaBlend(bool32 enable){
setAlphaBlend(bool32 enable)
{
if(rwStateCache.blendEnable != enable){ if(rwStateCache.blendEnable != enable){
rwStateCache.blendEnable = enable; rwStateCache.blendEnable = enable;
setGlRenderState(RWGL_BLEND, enable); setGlRenderState(RWGL_BLEND, enable);

View file

@ -416,86 +416,96 @@ rasterLock(Raster *raster, int32 level, int32 lockMode)
#endif #endif
} }
void void rasterUnlock(Raster *raster, int32 level){
rasterUnlock(Raster *raster, int32 level)
{
#ifdef RW_GLES1 #ifdef RW_GLES1
Gl1Raster *natras = GETGL1RASTEREXT(raster); Gl1Raster *natras = GETGL1RASTEREXT(raster);
assert(raster->pixels); assert(raster->pixels);
switch(raster->type){ switch(raster->type){
case Raster::NORMAL: case Raster::NORMAL:
case Raster::TEXTURE: case Raster::TEXTURE:
case Raster::CAMERATEXTURE: case Raster::CAMERATEXTURE:
if(raster->privateFlags & Raster::LOCKWRITE){ if(raster->privateFlags & Raster::LOCKWRITE){
if (level != 0) break; if(level != 0) break;
uint32 prev = bindTexture(natras->texid);
if(natras->isCompressed){
glCompressedTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat,
raster->width, raster->height, 0,
getLevelSize(raster, level),
raster->pixels);
}else{
int stride = raster->width * natras->bpp;
uint8_t* tmp = (uint8_t*)malloc(stride);
for (int y = 0; y < raster->height / 2; y++) {
uint8_t* a = (uint8_t*)raster->pixels + y * stride;
uint8_t* b = (uint8_t*)raster->pixels + (raster->height - 1 - y) * stride;
memcpy(tmp, a, stride); // === GUARDAR EN BACKING STORE ANTES DE SUBIR A GPU ===
memcpy(a, b, stride); if(natras->backingStore == nil){
memcpy(b, tmp, stride); int numLevels = natras->numLevels;
} // RasterLevels tiene: int numlevels; struct { uint32 size; uint8 *data; } levels[];
free(tmp); natras->backingStore = (RasterLevels*)malloc(
sizeof(RasterLevels) + sizeof(natras->backingStore->levels[0]) * numLevels);
natras->backingStore->numlevels = numLevels;
for(int i = 0; i < numLevels; i++){
uint32 sz = getLevelSize(raster, i);
natras->backingStore->levels[i].size = sz;
natras->backingStore->levels[i].data = (uint8*)malloc(sz);
memset(natras->backingStore->levels[i].data, 0, sz);
}
}
// copiar píxeles actuales al backing store
{
uint32 sz = getLevelSize(raster, level);
assert(level < natras->backingStore->numlevels);
memcpy(natras->backingStore->levels[level].data, raster->pixels, sz);
}
// === FIN BACKING STORE ===
if (raster->pixels != nil && natras->format == GL_RGBA && natras->type == GL_UNSIGNED_BYTE) { uint32 prev = bindTexture(natras->texid);
// convert to 16-bit
uint16_t* pixels16 = (uint16_t*)malloc(raster->width * raster->height * sizeof(uint16_t));
uint8_t* pixels8 = (uint8_t*)raster->pixels;
for (int i = 0; i < raster->width * raster->height; i++) { // flip vertical (igual que antes)
uint8_t r = pixels8[i * 4 + 0]; {
uint8_t g = pixels8[i * 4 + 1]; int stride = raster->width * natras->bpp;
uint8_t b = pixels8[i * 4 + 2]; uint8_t *tmp = (uint8_t*)malloc(stride);
uint8_t a = pixels8[i * 4 + 3]; for(int y = 0; y < raster->height / 2; y++){
uint8_t *a = (uint8_t*)raster->pixels + y * stride;
uint8_t *b = (uint8_t*)raster->pixels + (raster->height - 1 - y) * stride;
memcpy(tmp, a, stride);
memcpy(a, b, stride);
memcpy(b, tmp, stride);
}
free(tmp);
}
pixels16[i] = ((r >> 4) << 12) | ((g >> 4) << 8) | ((b >> 4) << 4) | (a >> 4); if(!natras->isCompressed){
} if(natras->format == GL_RGBA && natras->type == GL_UNSIGNED_BYTE){
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, raster->width, raster->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels16); // convertir RGBA8888 → RGBA4444
free(pixels16); uint16_t *pixels16 = (uint16_t*)malloc(raster->width * raster->height * 2);
} else uint8_t *pixels8 = (uint8_t*)raster->pixels;
{ for(int i = 0; i < raster->width * raster->height; i++){
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1); uint8_t r = pixels8[i*4+0];
glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat, uint8_t g = pixels8[i*4+1];
raster->width, raster->height, uint8_t b = pixels8[i*4+2];
0, natras->format, natras->type, raster->pixels); uint8_t a = pixels8[i*4+3];
} pixels16[i] = ((r>>4)<<12)|((g>>4)<<8)|((b>>4)<<4)|(a>>4);
} }
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA,
raster->width, raster->height, 0,
GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels16);
free(pixels16);
} else {
glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat,
raster->width, raster->height, 0,
natras->format, natras->type, raster->pixels);
}
}
if(natras->backingStore){ bindTexture(prev);
assert(level < natras->backingStore->numlevels); }
memcpy(natras->backingStore->levels[level].data, raster->pixels, break;
natras->backingStore->levels[level].size);
}
bindTexture(prev); case Raster::CAMERA:
} break;
break; }
case Raster::CAMERA: rwFree(raster->pixels);
// TODO: write? raster->pixels = nil;
break;
}
rwFree(raster->pixels);
raster->pixels = nil;
#endif #endif
raster->width = raster->originalWidth; raster->width = raster->originalWidth;
raster->height = raster->originalHeight; raster->height = raster->originalHeight;
raster->stride = raster->originalStride; raster->stride = raster->originalStride;
raster->pixels = raster->originalPixels; raster->pixels = raster->originalPixels;
raster->privateFlags = 0; raster->privateFlags = 0;
} }
int32 int32
@ -741,8 +751,8 @@ void evictRaster(Raster *raster);
static void* static void*
destroyNativeRaster(void *object, int32 offset, int32) destroyNativeRaster(void *object, int32 offset, int32)
{ {
Raster *raster = (Raster*)object; Raster *raster = (Raster*)object;
Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, object, offset); Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, object, offset);
#ifdef RW_GLES1 #ifdef RW_GLES1
evictRaster(raster); evictRaster(raster);
switch(raster->type){ switch(raster->type){
@ -769,10 +779,14 @@ destroyNativeRaster(void *object, int32 offset, int32)
natras->texid = 0; natras->texid = 0;
natras->fbo = 0; natras->fbo = 0;
free(natras->backingStore); if(natras->backingStore){
for(int i = 0; i < natras->backingStore->numlevels; i++)
free(natras->backingStore->levels[i].data);
free(natras->backingStore);
natras->backingStore = nil;
}
#endif #endif
return object; return object;
} }
static void* static void*