/************************************************************************ * Copyright (c) 2005-2007 tok@openlinux.org.uk * * * * This file contains code derived from information copyrighted by * * DMA Design. It may not be used in a commercial product. * * * * See license.txt for details. * * * * This notice may not be removed or altered. * ************************************************************************/ #ifndef OPENGTA_MAIN_H #define OPENGTA_MAIN_H #include #include #include #include #include #include "set.h" namespace OpenGTA { /** The common class for all graphics wrappers. * Contains a number of common variables; does essentially nothing. */ class GraphicsBase { public: GraphicsBase(); virtual ~GraphicsBase(); uint8_t getFormat(); typedef struct ObjectInfo { PHYSFS_uint32 width, height, depth; PHYSFS_uint16 sprNum, weight, aux; PHYSFS_sint8 status; PHYSFS_uint8 numInto; //PHYSFS_uint16 into[255]; // FIXME: MAX_INTO ??? } ObjectInfo; typedef struct LoadedAnim { LoadedAnim(size_t size) : frame(size) {} PHYSFS_uint8 block; PHYSFS_uint8 which; PHYSFS_uint8 speed; PHYSFS_uint8 frameCount; std::vector frame; } LoadedAnim; typedef struct DoorInfo { PHYSFS_sint16 rpx, rpy; PHYSFS_sint16 object; PHYSFS_sint16 delta; } DoorInfo; typedef struct HlsInfo { PHYSFS_sint16 h, l, s; } HlsInfo; typedef struct CarInfo { PHYSFS_sint16 width, height, depth; PHYSFS_sint16 sprNum; PHYSFS_sint16 weightDescriptor; PHYSFS_sint16 maxSpeed, minSpeed; PHYSFS_sint16 acceleration, braking; PHYSFS_sint16 grip, handling; // ... remaps HlsInfo remap24[12]; PHYSFS_uint8 remap8[12]; PHYSFS_uint8 vtype; PHYSFS_uint8 model; PHYSFS_uint8 turning; PHYSFS_uint8 damagable; PHYSFS_uint16 value[4]; PHYSFS_sint8 cx,cy; PHYSFS_uint32 moment; float rbpMass; float g1_Thrust; float tyreAdhesionX, tyreAdhesionY; float handBrakeFriction; float footBrakeFriction; float frontBrakeBias; PHYSFS_sint16 turnRatio; PHYSFS_sint16 driveWheelOffset; PHYSFS_sint16 steeringWheelOffset; float backEndSlideValue; float handBrakeSlideValue; PHYSFS_uint8 convertible; PHYSFS_uint8 engine; PHYSFS_uint8 radio; PHYSFS_uint8 horn; PHYSFS_uint8 soundFunction; PHYSFS_uint8 fastChangeFlag; PHYSFS_sint16 numDoors; DoorInfo door[4]; // FIXME: MAX_DOORS } CarInfo; /* * float->fixed: * fixed = int(floatnum * 65536) * * fixed->float * float = float(fixedNum)/65536 * * int->fixed * fixed = intNum << 16 * * fixed->int * int = fixedNum >> 16 */ typedef struct DeltaInfo { PHYSFS_uint16 size; unsigned char* ptr; } DeltaInfo; typedef struct SpriteInfo { PHYSFS_uint8 w; PHYSFS_uint8 h; PHYSFS_uint8 deltaCount; PHYSFS_uint16 size; PHYSFS_uint16 clut; PHYSFS_uint8 xoffset; PHYSFS_uint8 yoffset; PHYSFS_uint16 page; //unsigned char* ptr; DeltaInfo delta[33]; //FIXME: GTA_SPRITE_MAX_DELTAS } SpriteInfo; typedef struct SpriteNumbers { PHYSFS_uint16 GTA_SPRITE_ARROW; PHYSFS_uint16 GTA_SPRITE_DIGITS; PHYSFS_uint16 GTA_SPRITE_BOAT; PHYSFS_uint16 GTA_SPRITE_BOX; PHYSFS_uint16 GTA_SPRITE_BUS; PHYSFS_uint16 GTA_SPRITE_CAR; PHYSFS_uint16 GTA_SPRITE_OBJECT; PHYSFS_uint16 GTA_SPRITE_PED; PHYSFS_uint16 GTA_SPRITE_SPEEDO; PHYSFS_uint16 GTA_SPRITE_TANK; PHYSFS_uint16 GTA_SPRITE_TRAFFIC_LIGHTS; PHYSFS_uint16 GTA_SPRITE_TRAIN; PHYSFS_uint16 GTA_SPRITE_TRDOORS; PHYSFS_uint16 GTA_SPRITE_BIKE; PHYSFS_uint16 GTA_SPRITE_TRAM; PHYSFS_uint16 GTA_SPRITE_WBUS; PHYSFS_uint16 GTA_SPRITE_WCAR; PHYSFS_uint16 GTA_SPRITE_EX; PHYSFS_uint16 GTA_SPRITE_TUMCAR; PHYSFS_uint16 GTA_SPRITE_TUMTRUCK; PHYSFS_uint16 GTA_SPRITE_FERRY; enum SpriteTypes { ARROW = 0, DIGIT, BOAT, BOX, BUS, CAR, OBJECT, PED, SPEEDO, TANK, TRAFFIC_LIGHT, TRAIN, TRDOOR, BIKE, TRAM, WBUS, WCAR, EX, TUMCAR, TUMTRUCK, FERRY }; PHYSFS_uint16 reIndex(const PHYSFS_uint16 & id, const enum SpriteTypes & st) const; PHYSFS_uint16 countByType(const SpriteTypes & t) const; } SpriteNumbers; bool isAnimatedBlock(uint8_t area_code, uint8_t id); void prepareSideTexture(unsigned int idx, unsigned char* dst); void prepareLidTexture(unsigned int idx, unsigned char* dst); void prepareAuxTexture(unsigned int idx, unsigned char* dst); unsigned int getRandomPedRemapNumber(); unsigned int getPedRemapNumberType(unsigned int _type); SpriteNumbers spriteNumbers; CarInfo* findCarByModel(PHYSFS_uint8); size_t getNumCarModels() { return carInfos.size(); } unsigned char* getTmpBuffer(bool rgba); SpriteInfo* getSprite(size_t id) { return spriteInfos[id]; } virtual unsigned char* getSide(unsigned int idx, unsigned int palIdx, bool rgba) = 0; virtual unsigned char* getLid(unsigned int idx, unsigned int palIdx, bool rgba) = 0; virtual unsigned char* getAux(unsigned int idx, unsigned int palIdx, bool rgba) = 0; virtual unsigned char* getSpriteBitmap(size_t id, int remap, Uint32 delta) = 0; std::vector animations; std::vector spriteInfos; std::vector objectInfos; std::vector carInfos; bool getDeltaHandling(); void setDeltaHandling(bool delta_as_set); bool isBlockingSide(uint8_t id); void setupBlocking(const std::string & file); protected: void loadTileTextures(); void loadAnim(); void loadObjectInfo_shared(PHYSFS_uint64 offset); void loadSpriteNumbers_shared(PHYSFS_uint64 offset); void loadCarInfo_shared(PHYSFS_uint64 offset); void loadSpriteInfo_shared(PHYSFS_uint64 offset); void handleDeltas(const SpriteInfo & spriteinfo, unsigned char* buffer, Uint32 delta); void applyDelta(const SpriteInfo & spriteInfo, unsigned char* buffer, Uint32 offset, const DeltaInfo & deltaInfo, bool mirror = false); PHYSFS_file* fd; unsigned char* rawTiles; unsigned char* rawSprites; PHYSFS_uint32 sideSize; PHYSFS_uint32 lidSize; PHYSFS_uint32 auxSize; PHYSFS_uint32 animSize; PHYSFS_uint32 objectInfoSize; PHYSFS_uint32 carInfoSize; PHYSFS_uint32 spriteInfoSize; PHYSFS_uint32 spriteGraphicsSize; PHYSFS_uint32 spriteNumberSize; PHYSFS_uint32 auxBlockTrailSize; /* int loadSide(); int loadLid(); int loadAux(); int loadAnim(); int loadObject(); int loadCar(); int loadSpriteInfo(); int loadSpriteGraphics(); int loadSpriteNumbers();*/ PHYSFS_uint8 _topHeaderSize; unsigned char tileTmp[4096]; unsigned char tileTmpRGB[4096*3]; unsigned char tileTmpRGBA[4096*4]; bool delta_is_a_set; Util::Set sideTexBlockMove; unsigned int firstValidPedRemap; unsigned int lastValidPedRemap; }; // just a forward declaration class CityView; /** Loader for STYLE*.GRY files. * * Implements loading the 8-bit graphic files. */ class Graphics8Bit : public GraphicsBase { /** allow renderer direct access to members */ friend class CityView; public: /** Constructor for graphics loader. * @param style a valid filename (maybe uppercase depending on your files) */ Graphics8Bit(const std::string& style); /** Destructor cleans all rawdata caches. */ ~Graphics8Bit(); /** Helper to apply palettes to various raw bitmaps. * @see Graphics8Bit * @see Font */ class RGBPalette { private: unsigned char data[256*3]; public: /** Empty constructor. * You HAVE to call loadFromFile() function when using this constructor!. */ RGBPalette(); /** Formerly private member, now exposed for Font class; take care. * @param fd PHYSFS_file* handle. */ int loadFromFile(PHYSFS_file* fd); /** Constructor from PHYFS_file. * @param fd PHYSFS_file* handle */ RGBPalette(PHYSFS_file* fd); /** Constructor from filename. * @param filename a palette file name */ RGBPalette(const std::string& palette); /** Transforms an input buffer using the palette stored in this instance. * @param len length of the src buffer (in byte) * @param src pointer to src buffer * @param dst pointer to dst buffer (must exist and be large enough) * @param rgba use 'true' to create a RGBA image, or 'false' (default) for RGB */ void apply(unsigned int len, const unsigned char* src, unsigned char* dst, bool rgba = false); }; unsigned char* getSide(unsigned int idx, unsigned int palIdx, bool rgba); unsigned char* getLid(unsigned int idx, unsigned int palIdx, bool rgba); unsigned char* getAux(unsigned int idx, unsigned int palIdx, bool rgba); unsigned char* getSpriteBitmap(size_t id, int remap, Uint32 delta); void dump(); private: PHYSFS_uint32 paletteSize; PHYSFS_uint32 remapSize; PHYSFS_uint32 remapIndexSize; protected: void loadHeader(); void loadPalette(); void loadRemapTables(); void loadRemapIndex(); void loadObjectInfo(); void loadCarInfo(); void loadSpriteInfo(); void loadSpriteGraphics(); void loadSpriteNumbers(); void applyRemap(unsigned int len, unsigned int which, unsigned char* buffer); RGBPalette* masterRGB; PHYSFS_uint8 remapTables[256][256]; PHYSFS_uint8 remapIndex[256][4]; }; class Graphics24Bit : public GraphicsBase { public: Graphics24Bit(const std::string & style); ~Graphics24Bit(); unsigned char* getSide(unsigned int idx, unsigned int palIdx, bool rgba); unsigned char* getLid(unsigned int idx, unsigned int palIdx, bool rgba); unsigned char* getAux(unsigned int idx, unsigned int palIdx, bool rgba); unsigned char* getSpriteBitmap(size_t id, int remap, Uint32 delta); void dumpClut(const char* fname); protected: void loadHeader(); void loadClut(); void loadPalIndex(); void loadObjectInfo(); void loadCarInfo(); void loadSpriteInfo(); void loadSpriteGraphics(); void loadSpriteNumbers(); void applyClut(unsigned char* src, unsigned char* dst, const size_t & len, const PHYSFS_uint16 & clutIdx, bool rgba); private: PHYSFS_uint32 clutSize; PHYSFS_uint32 pagedClutSize; PHYSFS_uint32 tileclutSize; PHYSFS_uint32 spriteclutSize; PHYSFS_uint32 newcarclutSize; PHYSFS_uint32 fontclutSize; PHYSFS_uint32 paletteIndexSize; unsigned char* rawClut; PHYSFS_uint16* palIndex; }; class NavData; // see navdata.h #define GTA_MAP_MAXDIMENSION 256 /** the wrapper for the CMP (compressed map) files */ class Map { friend class MapViewGL; public: Map(const std::string& filename); ~Map(); typedef struct BlockInfo { PHYSFS_uint16 typeMap; PHYSFS_uint8 typeMapExt; PHYSFS_uint8 left, right, top, bottom, lid; inline bool upOk() { return (typeMap & 1); } inline bool downOk() { return (typeMap & 2); } inline bool leftOk() { return (typeMap & 4); } inline bool rightOk() { return (typeMap & 8); } inline uint8_t blockType() { return ((typeMap & 16 ? 1 : 0) + (typeMap & 32 ? 2 : 0) + (typeMap & 64 ? 4 : 0)); } inline bool isFlat() { return (typeMap & 128); } inline uint8_t slopeType() { return ((typeMap & 256 ? 1 : 0) + (typeMap & 512 ? 2 : 0) + (typeMap & 1024 ? 4 : 0) + (typeMap & 2048 ? 8 : 0) + (typeMap & 4096 ? 16 : 0) + (typeMap & 8192 ? 32 : 0)); } inline uint8_t rotation() { return ((typeMap & 16384 ? 1 : 0) + (typeMap & 32768 ? 2 : 0)); } /* m1win seems to indicate: * 000 - Nothing * 001 - traffic lights * 010 - invalid * 011 - invalid * 100 - railway end turn * 101 - railway start turn * 110 - railway station * 111 - railway station train */ inline void setUpOk(bool v) { if (v) typeMap |= 1; else typeMap &= ~1; } inline void setDownOk(bool v) { if (v) typeMap |= 2; else typeMap &= ~2; } inline void setLeftOk(bool v) { if (v) typeMap |= 4; else typeMap &= ~4; } inline void setRightOk(bool v) { if (v) typeMap |= 8; else typeMap &= ~8; } inline void setIsFlat(bool v) { if (v) typeMap |= 128; else typeMap &= ~128; } void setBlockType(uint8_t v); void setSlopeType(uint8_t v); void setRotation(uint8_t v); inline bool trafficLights() { return (typeMapExt & 1); } inline bool railEndTurn() { return (typeMapExt & 4); } inline bool railStartTurn() { return ((typeMapExt & 4) && (typeMapExt &1)); } inline bool railStation() { return ((typeMapExt & 4) && (typeMapExt & 2));} inline bool railStationTrain() { return ((typeMapExt & 4) && (typeMapExt & 2) && (typeMapExt & 1)); } inline uint8_t remapIndex() { return ((typeMapExt & 8 ? 1 : 0) + (typeMapExt & 16 ? 2 : 0));} inline bool flipTopBottom() { return (typeMapExt & 32); } inline bool flipLeftRight() { return (typeMapExt & 64); } inline bool railway() { return (typeMapExt & 128); } } BlockInfo; typedef struct { PHYSFS_uint16 x, y, z; PHYSFS_uint8 type; PHYSFS_uint8 remap; PHYSFS_uint16 rotation; // see: cds.doc PHYSFS_uint16 pitch; PHYSFS_uint16 roll; } ObjectPosition; typedef struct Location { Location(); Location(const Location & other); PHYSFS_uint8 x, y, z; } Location; typedef std::multimap LocationMap; //... PHYSFS_uint16 getNumBlocksAt(PHYSFS_uint8 x, PHYSFS_uint8 y); PHYSFS_uint16 getNumBlocksAtNew(PHYSFS_uint8 x, PHYSFS_uint8 y); BlockInfo* getBlockAt(PHYSFS_uint8 x, PHYSFS_uint8 y, PHYSFS_uint8 z); BlockInfo* getBlockAtNew(PHYSFS_uint8 x, PHYSFS_uint8 y, PHYSFS_uint8 z); BlockInfo* getBlockByInternalId(PHYSFS_uint16 id); PHYSFS_uint16 getInternalIdAt(PHYSFS_uint8 x, PHYSFS_uint8 y, PHYSFS_uint8 z); void dump(); NavData *nav; ObjectPosition *objects; PHYSFS_uint16 numObjects; const Location & getNearestLocationByType(uint8_t t, uint8_t x, uint8_t y); const LocationMap & getLocationMap() { return locations; } protected: PHYSFS_uint32 base[GTA_MAP_MAXDIMENSION][GTA_MAP_MAXDIMENSION]; PHYSFS_uint16 *column; BlockInfo *block; LocationMap locations; private: PHYSFS_file* fd; PHYSFS_uint8 styleNumber; PHYSFS_uint32 routeSize; PHYSFS_uint32 objectPosSize; PHYSFS_uint32 columnSize; PHYSFS_uint32 blockSize; PHYSFS_uint32 navDataSize; int loadHeader(); int loadBase(); int loadColumn(); int loadBlock(); void loadObjects(); void loadRoutes(); void loadLocations(); void loadNavData(const size_t level_num); static const PHYSFS_uint8 _topHeaderSize = 28; static const PHYSFS_uint64 _baseSize = 262144; }; class MessageDB { public: MessageDB(); MessageDB(const std::string &file); ~MessageDB(); void load(const std::string &file); const std::string& getText(const char* id); const std::string& getText(const std::string &id); const std::string& getText(const uint32_t id); private: std::map messages; std::string _error; }; class Font { public: class Character { public: Character(PHYSFS_file*, uint8_t); ~Character(); uint8_t width; uint8_t *rawData; }; Font(const std::string &file); ~Font(); uint8_t getNumChars() { return numChars; } uint8_t getCharHeight() { return charHeight; } Character *getCharById(size_t num) ; size_t getIdByChar(const char c) ; uint8_t getMoveWidth(const char c); void addMapping(char c, size_t num); void dumpAs(const char* filename, size_t id) ; unsigned char* getCharacterBitmap(size_t num, unsigned int *width, unsigned int *height); private: void loadMapping(const std::string &name); void readHeader(PHYSFS_file*); uint8_t charHeight; uint8_t numChars; std::vector chars; std::map mapping; Graphics8Bit::RGBPalette palette; unsigned char *workBuffer; }; } #endif