// vim: set sts=2 ts=8 sw=2 tw=99 et: // ============================================================================= // SourcePawn // Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. // ============================================================================= // // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License, version 3.0, as published by the // Free Software Foundation. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // You should have received a copy of the GNU General Public License along with // this program. If not, see . // // As a special exception, AlliedModders LLC gives you permission to link the // code of this program (as well as its derivative works) to "Half-Life 2," the // "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software // by the Valve Corporation. You must obey the GNU General Public License in // all respects for all other code used. Additionally, AlliedModders LLC grants // this exception to all derivative works. AlliedModders LLC defines further // exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), // or . #ifndef _INCLUDE_SPFILE_HEADERS_H #define _INCLUDE_SPFILE_HEADERS_H #include #include namespace sp { struct SmxConsts { // SourcePawn File Format (SPFF) magic number. static const uint32_t FILE_MAGIC = 0x53504646; // File format verison number. // 0x0101 - SourcePawn 1.0; initial version used by SourceMod 1.0. // 0x0102 - SourcePawn 1.1; used by SourceMod 1.1+. // 0x0200 - Used by spcomp2. // // The major version bits (8-15) indicate a product number. Consumers should // reject any version for a different product. // // The minor version bits (0-7) indicate a compatibility revision. Any minor // version higher than the current version should be rejected. static const uint16_t SP1_VERSION_1_0 = 0x0101; static const uint16_t SP1_VERSION_1_1 = 0x0102; static const uint16_t SP1_VERSION_1_7 = 0x0107; static const uint16_t SP1_VERSION_MIN = SP1_VERSION_1_0; static const uint16_t SP1_VERSION_MAX = SP1_VERSION_1_7; static const uint16_t SP2_VERSION_MIN = 0x0200; static const uint16_t SP2_VERSION_MAX = 0x0200; // Compression types. static const uint8_t FILE_COMPRESSION_NONE = 0; static const uint8_t FILE_COMPRESSION_GZ = 1; // SourcePawn 1. static const uint8_t CODE_VERSION_JIT_1_0 = 9; static const uint8_t CODE_VERSION_JIT_1_1 = 10; static const uint8_t CODE_VERSION_JIT_1_7 = 11; static const uint8_t CODE_VERSION_SP1_MIN = CODE_VERSION_JIT_1_0; static const uint8_t CODE_VERSION_SP1_MAX = CODE_VERSION_JIT_1_1; // For SP1 consumers, the container version may not be checked, but usually // the code version is. This constant allows newer containers to be rejected // in those applications. static const uint8_t CODE_VERSION_REJECT = 0x7F; }; // These structures are byte-packed. #if defined __GNUC__ # pragma pack(1) #else # pragma pack(push) # pragma pack(1) #endif // The very first bytes in a .smx file. The .smx file format is a container for // arbitrary sections, though to actually load a .smx file certain sections // must be present. The on-disk format has four major regions, in order: // 1. The header (sp_file_hdr_t). // 2. The section list (sp_file_section_t). // 3. The string table. // 4. The section contents. // // Although any part of the file after the header can be compressed, by default // only the section contents are, and the section list and string table are not. typedef struct sp_file_hdr_s { // Magic number and version number. uint32_t magic; uint16_t version; // disksize, imagesize, and dataoffs (at the end) describe a region of the // file that may be compressed. The region must occur after the initial // sp_file_hdr_t header. For SourceMod compatibility, the meanings are as // follows. // // Without compression: // imagesize is the amount of bytes that must be read into memory to parse // the SMX container, starting from the first byte of the file. // disksize is undefined. // dataoffs is undefined. // // With compression: // dataoffs is an offset to the start of the compression region. // disksize is the length of the compressed region, in bytes, plus dataoffs. // imagesize is the size of the entire SMX container after decompression. // // This means that at least |imagesize-dataoffs| must be allocated to // decompress, and the compressed region's length is |datasize-dataoffs|. // // The compressed region should always be expanded "in-place". That is, to // parse the container, the compressed bytes should be replaced with // decompressed bytes. // // Note: This scheme may seem odd. It's a combination of historical debt and // previously unspecified behavior. The original .amx file format contained // an on-disk structure that supported an endian-agnostic variable-length // encoding of its data section, and this structure was loaded directly into // memory and used as the VM context. AMX Mod X later developed a container // format called ".amxx" as a "universal binary" for 32-bit and 64-bit // plugins. This format dropped compact encoding, but supported gzip. The // disksize/imagesize oddness made its way to this file format. When .smx // was created for SourceMod, it persisted even though AMX was dropped // entirely. So it goes. uint8_t compression; uint32_t disksize; uint32_t imagesize; // Number of named file sections. uint8_t sections; // Offset to the string table. Each string is null-terminated. The string // table is only used for strings related to parsing the container itself. // For SourcePawn, a separate ".names" section exists for Pawn-specific data. uint32_t stringtab; // Offset to where compression begins. uint32_t dataoffs; } sp_file_hdr_t; // Each section is written immediately after the header. typedef struct sp_file_section_s { uint32_t nameoffs; /**< Offset into the string table. */ uint32_t dataoffs; /**< Offset into the file for the section contents. */ uint32_t size; /**< Size of this section's contents. */ } sp_file_section_t; // Code section. This is used only in SP1, but is emitted by default for legacy // systems which check |codeversion| but not the SMX file version. typedef struct sp_file_code_s { uint32_t codesize; /**< Size of the code section. */ uint8_t cellsize; /**< Cellsize in bytes. */ uint8_t codeversion; /**< Version of opcodes supported. */ uint16_t flags; /**< Flags. */ uint32_t main; /**< Address to "main". */ uint32_t code; /**< Offset to bytecode, relative to the start of this section. */ } sp_file_code_t; #if defined __GNUC__ # pragma pack() #else # pragma pack(pop) #endif } // namespace sp #endif //_INCLUDE_SPFILE_HEADERS_H