Added new image cache system, 5k super ultra wide resolutions work, screen resolution set from the ini file.

This commit is contained in:
Justin Marshall
2020-06-23 16:31:16 -07:00
parent e93b511b53
commit 6d50fb6fca
13 changed files with 332 additions and 95 deletions
+2
View File
@@ -554,6 +554,8 @@ set(src_redalert
./RedAlert/TEXTBTN.H
./RedAlert/THEME.CPP
./RedAlert/THEME.H
./RedAlert/TEXCACHE.CPP
./RedAlert/TEXCACHE.H
./RedAlert/TILESET.CPP
./RedAlert/TOGGLE.CPP
./RedAlert/TOGGLE.H
-1
View File
@@ -3659,7 +3659,6 @@ void CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNum
INT_PTR shape_pointer;
#endif //WIN32
/*
** Special kludge for E3 to prevent crashes
*/
+116
View File
@@ -0,0 +1,116 @@
// FileBinary.h
//
class WwFile {
public:
static bool FileExists(const char* name) {
FILE* f = fopen(name, "rb");
if (f) {
fclose(f);
return true;
}
return false;
}
WwFile() {
file = NULL;
length = -1;
}
~WwFile() {
if (file != NULL) {
fclose(file);
file = NULL;
}
}
void InitOpen(const char* name) {
file = fopen(name, "rb");
GetFileLength();
}
void InitWrite(const char* name) {
file = fopen(name, "wb");
}
void InitAppend(const char* name) {
file = fopen(name, "ab");
}
void Scanf(char* format, ...) {
va_list arg;
int done;
va_start(arg, format);
done = vfscanf(file, format, arg);
va_end(arg);
}
void Printf(char* format, ...) {
va_list argptr;
static char string[4096];
va_start(argptr, format);
vsprintf(string, format, argptr);
va_end(argptr);
fprintf(file, string);
}
void Seek(int64_t pos, int set) {
_fseeki64(file, pos, set);
}
void Read(void* data, int size) {
fread(data, 1, size, file);
}
void Write(void* data, int size) {
fwrite(data, 1, size, file);
}
template<class type> size_t ReadBig(type& c) {
size_t r = Read(&c, sizeof(c));
return r;
}
template<class type> size_t ReadBigArray(type* c, int count) {
size_t r = Read(c, sizeof(c[0]) * count);
return r;
}
template<class type> size_t WriteBig(const type& c) {
type b = c;
return Write(&b, sizeof(b));
}
template<class type> size_t WriteBigArray(const type* c, int count) {
size_t r = 0;
for (int i = 0; i < count; i++) {
r += Write(c[i], sizeof(type));
}
return r;
}
bool EndOfFile(void) {
return Tell() >= length;
}
int64_t Tell(void) {
return _ftelli64(file);
}
void Flush(void) {
fflush(file);
}
private:
void GetFileLength(void) {
int c = ftell(file);
fseek(file, 0, SEEK_END);
length = ftell(file);
fseek(file, c, SEEK_SET);
}
FILE* file;
int length;
};
+4 -4
View File
@@ -182,8 +182,8 @@ unsigned short Hard_Error_Occured = 0;
WWMouseClass * WWMouse = NULL;
GraphicBufferClass SysMemPage(DEFAULT_SCREEN_WIDTH, 200, (void*)NULL);
WinTimerClass * WindowsTimer=NULL;
int ScreenWidth=3072;
int ScreenHeight=3072;
int ScreenWidth=6072;
int ScreenHeight=6072;
GraphicBufferClass ModeXBuff;
bool InMovie = FALSE; //Are we currently playing a VQ movie?
HANDLE hInstance;
@@ -740,8 +740,8 @@ int MenuList[][8]={
#ifdef WIN32
GraphicBufferClass VisiblePage;
GraphicBufferClass HiddenPage;
GraphicViewPortClass SeenBuff(&VisiblePage, 0, 0, 3072, 3072);
GraphicViewPortClass HidPage(&HiddenPage, 0, 0, 3072, 3072);
GraphicViewPortClass SeenBuff(&VisiblePage, 0, 0, 6072, 6072);
GraphicViewPortClass HidPage(&HiddenPage, 0, 0, 6072, 6072);
#else
GraphicBufferClass HidPage(DEFAULT_SCREEN_WIDTH, 201, (void*)NULL);
GraphicBufferClass SeenBuff(320, 200, (void *)0xA0000L);
+2
View File
@@ -469,6 +469,7 @@ extern "C" {
void GScreenClass::Blit_Display(void)
{
#if 0
BEnd(BENCH_BLIT_DISPLAY);
#ifdef WIN32
if (SeenBuff.Get_Width()!=320) {
@@ -482,6 +483,7 @@ void GScreenClass::Blit_Display(void)
#else
Shadow_Blit(0, 0, 320, 200, HidPage, SeenPage, ShadowPage->Get_Buffer());
#endif
#endif
}
+1 -1
View File
@@ -95,7 +95,7 @@
*=============================================================================================*/
inline int Lepton_To_Pixel(LEPTON lepton)
{
return (((int)(signed short)lepton * ICON_PIXEL_W) + (ICON_LEPTON_W / 2) - ((lepton < 0) ? (ICON_LEPTON_W - 1) : 0)) / ICON_LEPTON_W;
return (((int)(int)lepton * ICON_PIXEL_W) + (ICON_LEPTON_W / 2) - ((lepton < 0) ? (ICON_LEPTON_W - 1) : 0)) / ICON_LEPTON_W;
}
+3
View File
@@ -32,6 +32,9 @@
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
// jmarshall - force enabling optimizations, disable this if you need to debug it.
#pragma optimize("", on)
// jmarshall end
/***************************************************************************
* LCW_Uncomp -- Decompress an LCW encoded data block. *
-1
View File
@@ -169,7 +169,6 @@ void PowerClass::Draw_It(bool complete)
// jmarshall - render the world before the power bar.
RadarClass::Draw_It(complete);
// jmarshall end
{
BStart(BENCH_POWER);
+6 -6
View File
@@ -564,8 +564,8 @@ int PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , int
VisiblePage.Init( ScreenWidth, ScreenHeight, NULL, 0 ,(GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM) );
HiddenPage.Init( ScreenWidth, ScreenHeight, NULL, 0 ,(GBC_Enum)(0) );
SeenBuff.Attach( &VisiblePage, 0, 0, 3072, 3072 );
HidPage.Attach( &HiddenPage, 0, 0, 3072, 3072 );
SeenBuff.Attach( &VisiblePage, 0, 0, 6072, 6072 );
HidPage.Attach( &HiddenPage, 0, 0, 6072, 6072 );
Options.Adjust_Variables_For_Resolution();
@@ -733,8 +733,8 @@ bool InitDDraw(void)
VisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));
HiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);
SeenBuff.Attach(&VisiblePage, 0, 0, 3072, 3072);
HidPage.Attach(&HiddenPage, 0, 0, 3072, 3072);
SeenBuff.Attach(&VisiblePage, 0, 0, 6072, 6072);
HidPage.Attach(&HiddenPage, 0, 0, 6072, 6072);
return true;
}
@@ -930,8 +930,8 @@ void Read_Setup_Options( RawFileClass *config_file )
VideoBackBufferAllowed = ini.Get_Bool("Options", "VideoBackBuffer", true);
AllowHardwareBlitFills = ini.Get_Bool("Options", "HardwareFills", true);
ScreenWidth = 1280;
ScreenHeight = 720;
ScreenWidth = ini.Get_Int("Options", "Width", 1280);
ScreenHeight = ini.Get_Int("Options", "Height", 720);
/*
** See if an alternative socket number has been specified
+81
View File
@@ -0,0 +1,81 @@
// TexCache.cpp
//
#include "FUNCTION.H"
#include "TEXCACHE.H"
#define CACHE_HEADER_FILENAME "cache/cache_header_v1.vhdr"
#define CACHE_DATA_FILERNAME "cache/cache_data_v1.vdata"
TexCache texCache;
void TexCache::Init(void) {
// Check to see if we have a texture cache, if not make one.
if (!WwFile::FileExists(CACHE_HEADER_FILENAME) || !WwFile::FileExists(CACHE_DATA_FILERNAME)) {
texCacheHeaderFileWrite = new WwFile();
texCacheHeaderFileWrite->InitWrite(CACHE_HEADER_FILENAME);
texCacheDataFileWrite = new WwFile();
texCacheDataFileWrite->InitWrite(CACHE_DATA_FILERNAME);
}
else {
texCacheHeaderFileWrite = new WwFile();
texCacheHeaderFileWrite->InitAppend(CACHE_HEADER_FILENAME);
texCacheDataFileWrite = new WwFile();
texCacheDataFileWrite->InitAppend(CACHE_DATA_FILERNAME);
texCacheHeaderFileWrite->Seek(0, SEEK_END);
texCacheDataFileWrite->Seek(0, SEEK_END);
}
texCacheHeaderFile = new WwFile();
texCacheHeaderFile->InitOpen(CACHE_HEADER_FILENAME);
texCacheDataFile = new WwFile();
texCacheDataFile->InitOpen(CACHE_DATA_FILERNAME);
while (!texCacheHeaderFile->EndOfFile()) {
CacheEntry_t entry;
texCacheHeaderFile->Scanf("texture %s %d %d %d %llu\n", &entry.name, &entry.width, &entry.height, &entry.bpp, &entry.cachePosition);
entry.hash = generateHashValue(entry.name, strlen(entry.name));
cacheEntries.push_back(entry);
}
}
void TexCache::AddImage(const char* name, int width, int height, int bpp, byte* data) {
CacheEntry_t entry;
strcpy(entry.name, name);
entry.width = width;
entry.height = height;
entry.bpp = bpp;
entry.hash = generateHashValue(name, strlen(name));
entry.cachePosition = texCacheDataFileWrite->Tell();
cacheEntries.push_back(entry);
int length = entry.width * entry.height * entry.bpp;
texCacheDataFileWrite->Write(data, length);
texCacheHeaderFileWrite->Printf("texture %s %d %d %d %llu\n", entry.name, entry.width, entry.height, entry.bpp, entry.cachePosition);
texCacheHeaderFileWrite->Flush();
texCacheDataFileWrite->Flush();
}
bool TexCache::FindCachedImage(int64_t hash, int& width, int& height, int& bpp, byte* data) {
int cacheEntriesSize = cacheEntries.size();
if (cacheEntriesSize <= 0)
return false;
CacheEntry_t* cacheEntry = &cacheEntries[0];
for (int i = 0; i < cacheEntriesSize; i++, cacheEntry++) {
if (cacheEntry->hash == hash) {
int length = cacheEntry->width * cacheEntry->height * cacheEntry->bpp;
texCacheDataFile->Seek(cacheEntry->cachePosition, SEEK_SET);
texCacheDataFile->Read(data, length);
width = cacheEntry->width;
height = cacheEntry->height;
bpp = cacheEntry->bpp;
return true;
}
}
return false;
}
+48
View File
@@ -0,0 +1,48 @@
// Texcache.h
//
#include "FILEBINARY.H"
#include <vector>
/*
================
return a hash value for the filename
================
*/
__forceinline int64_t generateHashValue(const char* fname, const int size) {
uint32_t hash = 0x811c9dc5;
uint32_t prime = 0x1000193;
for (int i = 0; i < size; ++i) {
uint8_t value = fname[i];
hash = hash ^ value;
hash *= prime;
}
return hash;
}
struct CacheEntry_t {
char name[2048];
int64_t hash;
int width;
int height;
int bpp;
int64_t cachePosition;
};
class TexCache {
public:
void Init(void);
void AddImage(const char* name, int width, int height, int bpp, byte* data);
bool FindCachedImage(int64_t hash, int &width, int &height, int &bpp, byte *data);
private:
WwFile* texCacheHeaderFile;
WwFile* texCacheHeaderFileWrite;
WwFile* texCacheDataFile;
WwFile* texCacheDataFileWrite;
private:
std::vector< CacheEntry_t> cacheEntries;
};
extern TexCache texCache;
+66 -78
View File
@@ -47,6 +47,7 @@
#include "il/il.h"
#include "il/ilu.h"
#include "image.h"
#include "texcache.h"
#ifdef WINSOCK_IPX
#include "WSProto.h"
@@ -104,78 +105,67 @@ std::vector<Image_t *> loaded_images;
unsigned char* Draw_Dropsample(const unsigned char* in, int inwidth, int inheight, int outwidth, int outheight);
/*
================
return a hash value for the filename
================
*/
int64_t generateHashValue(const char* fname, const int size) {
uint32_t hash = 0x811c9dc5;
uint32_t prime = 0x1000193;
for (int i = 0; i < size; ++i) {
uint8_t value = fname[i];
hash = hash ^ value;
hash *= prime;
}
return hash;
}
/*
================
Image_WriteTGA
================
*/
void Image_WriteTGA(const char* filename, const byte* data, int width, int height, bool flipVertical) {
byte* buffer;
int i;
int bufferSize = width * height * 4 + 18;
int imgStart = 18;
buffer = (byte*)malloc(bufferSize);
memset(buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = width & 255;
buffer[13] = width >> 8;
buffer[14] = height & 255;
buffer[15] = height >> 8;
buffer[16] = 32; // pixel size
if (!flipVertical) {
buffer[17] = (1 << 5); // flip bit, for normal top to bottom raster order
}
// swap rgba to bgra
for (i = imgStart; i < bufferSize; i += 4) {
buffer[i] = data[i - imgStart + 2]; // blue
buffer[i + 1] = data[i - imgStart + 1]; // green
buffer[i + 2] = data[i - imgStart + 0]; // red
buffer[i + 3] = data[i - imgStart + 3]; // alpha
}
char temp[512];
strcpy(temp, filename);
COM_SetExtension(temp, strlen(temp), ".tga");
FILE* f = fopen(temp, "wb");
fwrite(buffer, 1, bufferSize, f);
fclose(f);
free(buffer);
}
static char* Image_GetGeneratedName(Image_t* image, const char* name, int houseid, int animid, int frameId, int64_t hash) {
static char generatedFileName[1024];
sprintf(generatedFileName, "cache/v4.%d.%d.%d.%d.tga", frameId, houseid, animid, hash);
sprintf(generatedFileName, "%s.%d.%d.%d.%d.tga", name, frameId, houseid, animid, hash);
return &generatedFileName[0];
}
static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int animid, int frameId, int64_t hash, bool writeGenerated) {
static bool Image_LoadFromCache(Image_t* image, const char* name, int houseid, int animid, int frameId, int64_t hash) {
static byte* Data = NULL;
if (Data == NULL) {
Data = new byte[8192 * 8192 * 4];
}
int Width, Height, Bpp;
if (!texCache.FindCachedImage(hash, Width, Height, Bpp, Data)) {
return false;
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
if (Bpp == 4) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, Data);
}
else if (Bpp == 3) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
}
else if (Bpp == 1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_R, GL_UNSIGNED_BYTE, Data);
}
else {
assert(!"Unknown BPP in image!");
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
strcpy(image->name, name);
if (houseid == -1)
image->HouseImages[0].image[animid][frameId] = texture;
else
image->HouseImages[houseid].image[animid][frameId] = texture;
//image->namehash = hash;
image->renderwidth[animid] = image->width = Width;
image->renderheight[animid] = image->height = Height;
//image->buffer[houseid][animid] = new unsigned char[Width * Height * Bpp];
//memcpy(image->buffer[houseid][animid], Data, Width * Height * Bpp);
return true;
}
static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int animid, int frameId, int64_t hash) {
const char* generatedName = Image_GetGeneratedName(image, name, houseid, animid, frameId, hash);
hash = generateHashValue(generatedName, strlen(generatedName));
// Check to see if we can load a generated image first.
// We only generate images that need a houseid
if (!writeGenerated && houseid >= 0) {
char* generatedImageName = Image_GetGeneratedName(image, name, houseid, animid, frameId, hash);
if (Image_loadHDImage(image, generatedImageName, houseid, animid, frameId, hash, true)) {
if (houseid >= 0) {
if (Image_LoadFromCache(image, generatedName, houseid, animid, frameId, hash)) {
return true;
}
}
@@ -183,6 +173,7 @@ static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int
ILuint ImageName;
ilGenImages(1, &ImageName);
ilBindImage(ImageName);
if (!ilLoadImage(name)) {
ilDeleteImages(1, &ImageName);
return false;
@@ -190,12 +181,9 @@ static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int
bool swapBGR = false;
if (strstr(name, ".TGA") || strstr(name, ".tga")) {
if (!writeGenerated)
{
iluFlipImage();
swapBGR = true;
}
}
ILuint Width, Height, Bpp;
Width = ilGetInteger(IL_IMAGE_WIDTH);
@@ -203,7 +191,7 @@ static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int
Bpp = ilGetInteger(IL_IMAGE_BPP);
ILubyte* Data = ilGetData();
if (Bpp == 4 && houseid != -1 && !writeGenerated) {
if (Bpp == 4 && houseid != -1) {
//Buffer_Enable_HD_Texture(true);
//Data = Draw_Dropsample(Data, Width, Height, Width / 2, Height / 2);
//Buffer_Enable_HD_Texture(false);
@@ -246,16 +234,14 @@ static bool Image_loadHDImage(Image_t *image, const char* name, int houseid, int
image->HouseImages[0].image[animid][frameId] = texture;
else
image->HouseImages[houseid].image[animid][frameId] = texture;
image->namehash = hash;
//image->namehash = hash;
image->renderwidth[animid] = image->width = Width;
image->renderheight[animid] = image->height = Height;
//image->buffer[houseid][animid] = new unsigned char[Width * Height * Bpp];
//memcpy(image->buffer[houseid][animid], Data, Width * Height * Bpp);
if (!writeGenerated && Bpp == 4 && houseid >= 0) {
char* generatedImageName = Image_GetGeneratedName(image, name, houseid, animid, frameId, hash);
Image_WriteTGA(generatedImageName, Data, Width, Height, false);
if (Bpp == 4 && houseid >= 0) {
texCache.AddImage(generatedName, Width, Height, Bpp, Data);
Console_Printf("Writing %s to cache %s\n", image->name, name);
Sleep(0);
}
@@ -347,7 +333,7 @@ Image_t* Image_LoadImage(const char* name, bool loadAnims, bool loadHouseColor)
if (!loadAnims) {
unsigned char remap[3] = { 0, 0, 0 };
if (!Image_loadHDImage(image, name, -1, 0, 0, hash, false)) {
if (!Image_loadHDImage(image, name, -1, 0, 0, hash)) {
delete image;
return NULL;
}
@@ -355,13 +341,13 @@ Image_t* Image_LoadImage(const char* name, bool loadAnims, bool loadHouseColor)
else {
byte* palette = (byte *)CCPalette.Get_Data();
for (int i = 0; i < MAX_MPLAYER_COLORS; i++) {
if (!Image_loadHDImage(image, name, i, 0, 0, hash, false)) {
if (!Image_loadHDImage(image, name, i, 0, 0, hash)) {
delete image;
return NULL;
}
}
}
image->namehash = hash;
loaded_images.push_back(image);
return image;
}
@@ -510,7 +496,7 @@ void Image_Add8BitImage(Image_t *image, int HouseId, int ShapeID, int Width, int
}
bool Image_Add32BitImage(const char *name, Image_t* image, int HouseId, int ShapeID, int frameId) {
return Image_loadHDImage(image, name, HouseId, ShapeID, frameId, image->namehash, false);
return Image_loadHDImage(image, name, HouseId, ShapeID, frameId, image->namehash);
}
BOOL Set_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel) {
@@ -772,6 +758,8 @@ void Create_Main_Window ( HANDLE instance , int command_show , int width , int h
ilInit();
texCache.Init();
SDL_Init(SDL_INIT_VIDEO);
game_window = SDL_CreateWindow(WINDOW_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
game_context = SDL_GL_CreateContext(game_window);
-1
View File
@@ -3786,7 +3786,6 @@ void ImGui::NewFrame(bool clearCmdList)
g.ForegroundDrawList.ResetForNewFrame();
g.ForegroundDrawList.PushClipRectFullScreen();
g.DrawData.Clear();
}