// 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 - Initial version used by spcomp1 and SourceMod 1.0.
// 0x0102 - Used by spcomp1 and SourceMod 1.1+.
// 0x0103 - Used by SourceMod 1.7+.
// 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_MIN = 0x0101;
static const uint16_t SP1_VERSION_MAX = 0x0103;
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.0.
static const uint8_t CODE_VERSION_JIT1 = 9;
// SourcePawn 1.1.
static const uint8_t CODE_VERSION_JIT2 = 10;
// 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;
// Compression algorithm. If the file is not compressed, then imagesize and
// disksize are the same value, and dataoffs is 0.
//
// The start of the compressed region is indicated by dataoffs. The length
// of the compressed region is (disksize - dataoffs). The amount of memory
// required to hold the decompressed bytes is (imagesize - dataoffs). The
// compressed region should be expanded in-place. That is, bytes before
// "dataoffs" should be retained, and the decompressed region should be
// appended.
//
// |imagesize| is the amount of memory required to hold the entire container
// in memory.
//
// 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