123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- #include "stdafx.h"
- #include "cPortal.h"
- #include "cByteStream.h"
- /* Portal Types:
- 01 - Type 1 models
- 02 - Type 2 models (Modelgroups)
- 03 - Animations
- 04 - Palettes
- 05 - Texture lookups
- 06 - Textures
- 08 - Texture Lookups
- 0A - Sounds
- 0D - Dungeon Parts
- 0E - UI text
- 0F - palette lookups?
- 13 - Worldinfo
- 22 - String lists
- 25 - More string lists
- 27 - Magic Strings
- 31 - Character creation strings
- */
- PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
- cPortal::cPortal()
- {
- m_tfPortal = new cTurbineFile();
- m_tfPortal->LoadFile("client_portal.dat");
-
- TCHAR szEXEPathname[_MAX_PATH];
- GetModuleFileName(NULL, szEXEPathname, _MAX_PATH);
- *(strrchr(szEXEPathname, '\\')+1) = 0;
- strcat(szEXEPathname, "client_highres.dat");
- FILE *ftest = fopen(szEXEPathname,"rb");
- if (ftest)
- {
- fclose(ftest);
- m_tfPortalHighRes = new cTurbineFile();
- m_tfPortalHighRes->LoadFile("client_highres.dat");
- }
- else
- m_tfPortalHighRes = NULL;
- }
- cPortal::~cPortal()
- {
- if (m_tfPortal)
- delete m_tfPortal;
- if (m_tfPortalHighRes)
- delete m_tfPortalHighRes;
- }
- cPortalFile * cPortal::OpenEntry( DWORD dwID )
- {
- cPortalFile *tp = NULL;
- if (m_tfPortalHighRes)
- tp = m_tfPortalHighRes->OpenEntry(dwID);
- if (tp)
- return tp;
- else return m_tfPortal->OpenEntry(dwID);
- }
- int cPortal::HighestPowerOfTwo(DWORD In)
- {
- int tp = -1;
- for (int i=0;i<32;i++)
- {
- if (In & 1) tp = i;
- In >>= 1;
- }
- return tp;
- }
- DWORD cPortal::FindTexturePalette(DWORD Texture, std::vector<stPaletteSwap> *vPaletteSwaps, float fTransTex, float fTransPix)
- {
- //TODO: Implement the transparency!
- cPortalFile *pfTex = OpenEntry(Texture);
- if (!pfTex)
- return 0;
- //redirect if it can find it
- if ((Texture & 0xFF000000) == 0x05000000)
- {
- DWORD NumIDs = *((DWORD *) (pfTex->data + 9));
- for (DWORD i=13; i<=13 + NumIDs*4; i+=4)
- {
- DWORD tp = FindGraphic(*((DWORD *) (pfTex->data + i)), vPaletteSwaps, fTransTex, fTransPix);
- if (tp)
- {
- m_mGraphicEdgeCache[Texture] = m_mGraphicEdgeCache[*((DWORD *) (pfTex->data + i))];
- return tp;
- }
- }
- }
- return 0;
- }
- DWORD cPortal::FindGraphic(DWORD ID, std::vector<stPaletteSwap> *vPaletteSwaps, float fTransTex, float fTransPix)
- {
- //Pull it out of the cache, if possible...
- QWORD Hash = ID | ((QWORD) ID << 32);
- int num = 0;
- if (vPaletteSwaps)
- {
- for (std::vector<stPaletteSwap>::iterator i = vPaletteSwaps->begin(); i != vPaletteSwaps->end(); i++)
- {
- Hash += num*((QWORD) i->newPalette << 40);
- Hash += num*((QWORD) i->length << 32);
- Hash += num*((QWORD) i->offset << 24);
- Hash += num++;
- }
- }
- Hash += (QWORD) (*((DWORD *) &fTransTex))*72;
- Hash += (QWORD) (*((DWORD *) &fTransPix))*9727;
- if (m_mGraphicCache.find(Hash) != m_mGraphicCache.end())
- return m_mGraphicCache[Hash];
-
- //Open object and make sure it exists...
- cPortalFile *pfUI = OpenEntry(ID);
- if (!pfUI)
- return 0;
- cByteStream pBS(pfUI->data, pfUI->length);
- pBS.ReadBegin();
- //Load and parse image
- DWORD dwPicID = pBS.ReadDWORD();
- DWORD unk = pBS.ReadDWORD();
- DWORD sizeX = pBS.ReadDWORD();
- DWORD sizeY = pBS.ReadDWORD();
- DWORD format = pBS.ReadDWORD();
- DWORD length = pBS.ReadDWORD();
-
- if (format == 0x1F4) //JPEG
- return 0;
- //If it's a palettized image, form the palette and transparencies
- DWORD palette = 0;
- DWORD *newPalette = 0;
- cPortalFile *pfPal = 0;
- bool newPalUsed = false;
- if ((format == 0x65) || (format == 0x29))
- {
- //Form the palette we're going to use
- memcpy(&palette, pfUI->data+24+length, sizeof(DWORD));
- pfPal = OpenEntry(palette);
- DWORD palentries = *((DWORD *) (pfPal->data+4));
- //Copy a new palette if we have to, otherwise just pull from memory
- newPalUsed = true;
- newPalette = new DWORD[palentries];
- memcpy(newPalette, pfPal->data+8, palentries*sizeof(DWORD));
- //Perform paletteswaps
- if (vPaletteSwaps)
- {
- for (std::vector<stPaletteSwap>::iterator i = vPaletteSwaps->begin(); i != vPaletteSwaps->end(); i++)
- {
- cPortalFile *pfPalNew = m_Portal->OpenEntry(0x04000000 | i->newPalette);
- if (!pfPalNew)
- return false;
- if (format == 0x29) //256 entries
- memcpy(&newPalette[i->offset], pfPalNew->data+8+(i->offset*sizeof(DWORD)), (i->length*sizeof(DWORD)));
- else //2048 entries
- memcpy(&newPalette[i->offset*8], pfPalNew->data+8+(i->offset*sizeof(DWORD))*8, (i->length*sizeof(DWORD))*8);
- }
- }
- //Overall Transparency
- DWORD tpf = ((DWORD) (0xFF * (1.0f-fTransTex))) << 24;
- for (DWORD i=0;i<palentries;i++)
- newPalette[i] = (newPalette[i] & 0x00FFFFFF) | tpf;
- //Color key 0 (0-7 for 2048-entry palettes, cuz turbine is gay)
- tpf = ((DWORD) (0xFF * (1.0f-fTransPix))) << 24;
- if (format == 0x29)
- {
- newPalette[0] = (newPalette[0] & 0x00FFFFFF) | tpf;
- }
- else
- {
- for (int l=0;l<8;l++)
- newPalette[l] = (newPalette[l] & 0x00FFFFFF) | tpf;
- }
- }
- //Figure out size of actual texture to store (must be powers of 2)
- int powx = HighestPowerOfTwo(sizeX), powy = HighestPowerOfTwo(sizeY);
- DWORD sizeX2 = 1 << powx;
- while (sizeX2 < sizeX)
- sizeX2 <<= 1;
- DWORD sizeY2 = 1 << powy;
- while (sizeY2 < sizeY)
- sizeY2 <<= 1;
- //Disable DXT textures for termserv
- //if (format >= 0x31545844) return 0;
- //Generate the OpenGL texture
- GLuint dwid = 0;
- glGenTextures( 1, &dwid );
- glBindTexture(GL_TEXTURE_2D, dwid);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
- if ((sizeX2 == sizeX) && (sizeY2 == sizeY) && (format != 0x65) && (format != 0x29))
- {
- //If it's just immediately loadable without any processing, do it!
- if (format == 0x31545844)
- glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, sizeX2,sizeY2, 0, length, pfUI->data+24);
- else if (format == 0x35545844)
- glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, sizeX2,sizeY2, 0, length, pfUI->data+24);
- else if (format == 0x15)
- glTexImage2D(GL_TEXTURE_2D, 0, 4, sizeX2,sizeY2, 0, GL_BGRA, GL_UNSIGNED_BYTE, pfUI->data+24);
- else if (format == 0xF3)
- glTexImage2D(GL_TEXTURE_2D, 0, 3, sizeX2,sizeY2, 0, GL_RGB, GL_UNSIGNED_BYTE, pfUI->data+24);
- else if (format == 0x14)
- glTexImage2D(GL_TEXTURE_2D, 0, 3, sizeX2,sizeY2, 0, GL_BGR, GL_UNSIGNED_BYTE, pfUI->data+24);
- else if ((format == 0x1C) || (format == 0xF4))
- glTexImage2D(GL_TEXTURE_2D, 0, 1, sizeX2,sizeY2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pfUI->data+24);
- else if ((format == 0x17) || (format == 0x1A)) //16-bit grayscale?
- glTexImage2D(GL_TEXTURE_2D, 0, 1, sizeX2,sizeY2, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, pfUI->data+24);
- else
- return NULL;
- }
- else
- {
- //Padding will be required, unfortunately...
- BYTE *tex = new BYTE[sizeX2*sizeY2*4];
- ZeroMemory(tex, sizeX2*sizeY2*4);
- for (DWORD y=0;y<sizeY2;y++)
- {
- for (DWORD x=0;x<sizeX2;x++)
- {
- if ((x < sizeX) && (y < sizeY))
- {
- //Image formats...
- switch (format)
- {
- case 0x14:
- case 0xF3: //RGB (24-bit color)
- *((DWORD *) &tex[4*sizeX2*y + x*4]) = *((DWORD *) (pfUI->data+24+(3*(sizeX*y+x)))) | 0xFF000000;
- break;
- case 0x15: //RGBA (32-bit color)
- *((DWORD *) &tex[4*sizeX2*y + x*4]) = *((DWORD *) (pfUI->data+24+(4*(sizeX*y+x))));
- break;
- case 0x65: //2-byte indexed, palette ID follows encoded data
- {
- WORD index = *((WORD *)(pfUI->data+24+(2*(sizeX*y+x))));
- *((DWORD *) &tex[4*sizeX2*y + x*4]) = newPalette[index]/* & 0x7FFFFFFF*/;
- }
- break;
- case 0x29: //1-byte indexed, palette ID follows encoded data
- {
- BYTE index = *((BYTE *)(pfUI->data+24+(sizeX*y+x)));
- *((DWORD *) &tex[4*sizeX2*y + x*4]) = newPalette[index]/* & 0x7FFFFFFF*/;
- }
- break;
- case 0x1C: //1-byte grayscale
- case 0xF4:
- {
- DWORD index = *((BYTE *)(pfUI->data+24+(sizeX*y+x)));
- *((DWORD *) &tex[4*sizeX2*y + x*4]) = index | (index << 8) | (index << 16) | 0xFF000000;
- }
- break;
- default:
- {
- return NULL;
- }
- }
- }
- else
- *((DWORD *) &tex[4*sizeX2*y + x*4]) = 0x00000000;
- }
- }
- glTexImage2D(GL_TEXTURE_2D, 0, 4, sizeX2,sizeY2, 0, GL_BGRA, GL_UNSIGNED_BYTE, tex);
- delete []tex;
- }
- //Store info to our caches
- POINTf tpoint( (float) sizeX/sizeX2, (float) sizeY/sizeY2 );
- m_mGraphicEdgeCache[ID] = tpoint;
- m_mGraphicCache[Hash] = dwid;
- //Clean up
- if (newPalUsed)
- delete []newPalette;
- return dwid;
- }
- POINTf cPortal::GetGraphicEdges(DWORD ID)
- {
- if (m_mGraphicEdgeCache.find(ID) == m_mGraphicEdgeCache.end())
- {
- POINTf tpzero( 0, 0 );
- return tpzero;
- }
- return m_mGraphicEdgeCache[ID];
- }
- DWORD cPortal::GetPoolSize()
- {
- DWORD size = 0;
- if (m_tfPortalHighRes) size += m_tfPortalHighRes->GetPoolSize();
- size += m_tfPortal->GetPoolSize();
- return size;
- }
|