amx

package module
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 4 Imported by: 0

README

goamx

goamx is a pure-Go loader and runtime for AMX/Pawn bytecode.

It can load AMX images, inspect public functions/native declarations/debug metadata, execute public functions, register Go native callbacks, read and write AMX memory, clone runtime state, and decode instructions.

The root package is the friendly host API. The vm subpackage exposes the lower-level virtual machine for bytecode tooling and advanced embedding.

Install

go get github.com/pawnkit/goamx

Root package example

package main

import (
	"fmt"
	"log"

	"github.com/pawnkit/goamx"
)

func main() {
	runtime, err := amx.LoadFile("gamemode.amx")
	if err != nil {
		log.Fatal(err)
	}
	defer runtime.Close()

	public, ok := runtime.FindPublic("OnGameModeInit")
	if !ok {
		log.Fatal("public not found")
	}

	value, err := runtime.ExecPublic(public.Index)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(value)
}

Low-level VM example

package main

import (
	"log"

	"github.com/pawnkit/goamx/vm"
)

func main() {
	machine, err := vm.LoadFile("gamemode.amx")
	if err != nil {
		log.Fatal(err)
	}

	instructions, err := machine.Decode()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("decoded %d instructions", len(instructions))
}

Development

task fmt
task check
task lint

Run go test -race ./... before changing runtime state, hooks, or native dispatch. See the compatibility policy for supported AMX images.

The public API is split into two packages:

  • github.com/pawnkit/goamx: ergonomic runtime API for hosts.
  • github.com/pawnkit/goamx/vm: lower-level VM, loader, decoder, and memory API.

Contributing

This is community tooling built in spare time. Bug reports, small fixes, and AMX compatibility fixtures are welcome. See CONTRIBUTING.md.

Documentation

Index

Constants

View Source
const (
	SymbolVariable  uint8 = 1
	SymbolReference uint8 = 2
	SymbolArray     uint8 = 3
	SymbolRefArray  uint8 = 4
	SymbolFunction  uint8 = 9
)
View Source
const (
	CellBytes                   = 4
	FlagDebug            uint16 = 0x0002
	FlagCompact          uint16 = 0x0004
	FlagSleep            uint16 = 0x0008
	FlagNoChecks         uint16 = 0x0010
	FlagNoRelocation     uint16 = 0x0200
	FlagNoDirectNative   uint16 = 0x0400
	FlagSYSREQN          uint16 = 0x0800
	FlagNativeRegistered uint16 = 0x1000
	FlagJITCompiled      uint16 = 0x2000
	FlagBrowse           uint16 = 0x4000
	FlagRelocated        uint16 = 0x8000
)

Variables

View Source
var (
	ErrInvalidAMX            = vm.ErrInvalidAMX
	ErrUnsupportedCellSize   = vm.ErrUnsupportedCellSize
	ErrUnsupportedExecution  = vm.ErrUnsupportedExecution
	ErrPublicIndexOutOfRange = vm.ErrPublicIndexOutOfRange
	ErrInvalidMemoryAccess   = vm.ErrInvalidMemoryAccess
	ErrInvalidInstruction    = vm.ErrInvalidInstruction
	ErrNotSleeping           = vm.ErrNotSleeping
	ErrExecutionPaused       = vm.ErrExecutionPaused
)
View Source
var ErrNativeNotDeclared = errors.New("native is not declared by the AMX image")

Functions

This section is empty.

Types

type Cell

type Cell int32

func CellFromFloat32

func CellFromFloat32(value float32) Cell

func (Cell) Float32

func (cell Cell) Float32() float32

type DebugAutomaton

type DebugAutomaton struct {
	ID      int16
	Address uint32
	Name    string
}

type DebugDimension

type DebugDimension struct {
	Tag  int16
	Size uint32
}

type DebugEvent

type DebugEvent struct {
	Instruction Instruction
	State       State
}

type DebugFile

type DebugFile struct {
	Address uint32
	Name    string
}

type DebugHook

type DebugHook func(DebugEvent) error

type DebugInfo

type DebugInfo struct {
	Files    []DebugFile
	Lines    []DebugLine
	Symbols  []DebugSymbol
	Tags     []DebugTag
	Automata []DebugAutomaton
	States   []DebugState
}

func (DebugInfo) FileAt

func (info DebugInfo) FileAt(address uint32) (DebugFile, bool)

func (DebugInfo) FunctionAt

func (info DebugInfo) FunctionAt(address uint32) (DebugSymbol, bool)

func (DebugInfo) LineAt

func (info DebugInfo) LineAt(address uint32) (DebugLine, bool)

type DebugLine

type DebugLine struct {
	Address uint32
	Line    int32
}

type DebugState

type DebugState struct {
	ID, Automaton int16
	Name          string
}

type DebugSymbol

type DebugSymbol struct {
	Address            uint32
	Tag                int16
	CodeStart, CodeEnd uint32
	Ident, Class       uint8
	Name               string
	Dimensions         []DebugDimension
}

type DebugTag

type DebugTag struct {
	ID   int16
	Name string
}

type EventKind added in v1.1.0

type EventKind string
const (
	EventInstruction EventKind = "instruction"
	EventPublicEnter EventKind = "public-enter"
	EventPublicExit  EventKind = "public-exit"
	EventNativeEnter EventKind = "native-enter"
	EventNativeExit  EventKind = "native-exit"
	EventException   EventKind = "exception"
)

type Info

type Info struct {
	Name           string
	FileVersion    uint8
	AMXVersion     uint8
	Flags          uint16
	DefinitionSize uint16
	CodeSize       int
	DataSize       int
	StackHeapSize  int
	NameLength     int
	HasMain        bool
}

type Instruction

type Instruction struct {
	Offset int32
	Opcode Opcode
	Params []Cell
	Size   int
}

type InstrumentationEvent added in v1.1.0

type InstrumentationEvent struct {
	Kind        EventKind
	Name        string
	Instruction Instruction
	State       State
	File        string
	Line        int
	Result      Cell
	Err         error
}

type InstrumentationHook added in v1.1.0

type InstrumentationHook func(InstrumentationEvent) error

type Library

type Library struct {
	Index int
	Name  string
}

type MemoryInfo

type MemoryInfo struct {
	CodeBytes      int
	DataBytes      int
	StackHeapBytes int
}

type Native

type Native struct {
	Index      int
	Name       string
	Registered bool
}

type NativeContext

type NativeContext interface {
	ReadString(addr Cell) (string, error)
	WriteString(addr Cell, value string) error
	ReadCell(addr Cell) (Cell, error)
	WriteCell(addr Cell, value Cell) error
	ReadBytes(addr Cell, size int) ([]byte, error)
	WriteBytes(addr Cell, value []byte) error
	CallPublic(name string, args ...Cell) (Cell, error)
}

type NativeFunc

type NativeFunc func(ctx NativeContext, params []Cell) (Cell, error)

type Opcode

type Opcode = vm.Opcode

Opcode is a 32-bit AMX instruction opcode.

const (
	OP_NONE        Opcode = vm.OP_NONE
	OP_LOAD_PRI    Opcode = vm.OP_LOAD_PRI
	OP_LOAD_ALT    Opcode = vm.OP_LOAD_ALT
	OP_LOAD_S_PRI  Opcode = vm.OP_LOAD_S_PRI
	OP_LOAD_S_ALT  Opcode = vm.OP_LOAD_S_ALT
	OP_LREF_PRI    Opcode = vm.OP_LREF_PRI
	OP_LREF_ALT    Opcode = vm.OP_LREF_ALT
	OP_LREF_S_PRI  Opcode = vm.OP_LREF_S_PRI
	OP_LREF_S_ALT  Opcode = vm.OP_LREF_S_ALT
	OP_LOAD_I      Opcode = vm.OP_LOAD_I
	OP_LODB_I      Opcode = vm.OP_LODB_I
	OP_CONST_PRI   Opcode = vm.OP_CONST_PRI
	OP_CONST_ALT   Opcode = vm.OP_CONST_ALT
	OP_ADDR_PRI    Opcode = vm.OP_ADDR_PRI
	OP_ADDR_ALT    Opcode = vm.OP_ADDR_ALT
	OP_STOR_PRI    Opcode = vm.OP_STOR_PRI
	OP_STOR_ALT    Opcode = vm.OP_STOR_ALT
	OP_STOR_S_PRI  Opcode = vm.OP_STOR_S_PRI
	OP_STOR_S_ALT  Opcode = vm.OP_STOR_S_ALT
	OP_SREF_PRI    Opcode = vm.OP_SREF_PRI
	OP_SREF_ALT    Opcode = vm.OP_SREF_ALT
	OP_SREF_S_PRI  Opcode = vm.OP_SREF_S_PRI
	OP_SREF_S_ALT  Opcode = vm.OP_SREF_S_ALT
	OP_STOR_I      Opcode = vm.OP_STOR_I
	OP_STRB_I      Opcode = vm.OP_STRB_I
	OP_LIDX        Opcode = vm.OP_LIDX
	OP_LIDX_B      Opcode = vm.OP_LIDX_B
	OP_IDXADDR     Opcode = vm.OP_IDXADDR
	OP_IDXADDR_B   Opcode = vm.OP_IDXADDR_B
	OP_ALIGN_PRI   Opcode = vm.OP_ALIGN_PRI
	OP_ALIGN_ALT   Opcode = vm.OP_ALIGN_ALT
	OP_LCTRL       Opcode = vm.OP_LCTRL
	OP_SCTRL       Opcode = vm.OP_SCTRL
	OP_MOVE_PRI    Opcode = vm.OP_MOVE_PRI
	OP_MOVE_ALT    Opcode = vm.OP_MOVE_ALT
	OP_XCHG        Opcode = vm.OP_XCHG
	OP_PUSH_PRI    Opcode = vm.OP_PUSH_PRI
	OP_PUSH_ALT    Opcode = vm.OP_PUSH_ALT
	OP_PUSH_R      Opcode = vm.OP_PUSH_R
	OP_PUSH_C      Opcode = vm.OP_PUSH_C
	OP_PUSH        Opcode = vm.OP_PUSH
	OP_PUSH_S      Opcode = vm.OP_PUSH_S
	OP_POP_PRI     Opcode = vm.OP_POP_PRI
	OP_POP_ALT     Opcode = vm.OP_POP_ALT
	OP_STACK       Opcode = vm.OP_STACK
	OP_HEAP        Opcode = vm.OP_HEAP
	OP_PROC        Opcode = vm.OP_PROC
	OP_RET         Opcode = vm.OP_RET
	OP_RETN        Opcode = vm.OP_RETN
	OP_CALL        Opcode = vm.OP_CALL
	OP_CALL_PRI    Opcode = vm.OP_CALL_PRI
	OP_JUMP        Opcode = vm.OP_JUMP
	OP_JREL        Opcode = vm.OP_JREL
	OP_JZER        Opcode = vm.OP_JZER
	OP_JNZ         Opcode = vm.OP_JNZ
	OP_JEQ         Opcode = vm.OP_JEQ
	OP_JNEQ        Opcode = vm.OP_JNEQ
	OP_JLESS       Opcode = vm.OP_JLESS
	OP_JLEQ        Opcode = vm.OP_JLEQ
	OP_JGRTR       Opcode = vm.OP_JGRTR
	OP_JGEQ        Opcode = vm.OP_JGEQ
	OP_JSLESS      Opcode = vm.OP_JSLESS
	OP_JSLEQ       Opcode = vm.OP_JSLEQ
	OP_JSGRTR      Opcode = vm.OP_JSGRTR
	OP_JSGEQ       Opcode = vm.OP_JSGEQ
	OP_SHL         Opcode = vm.OP_SHL
	OP_SHR         Opcode = vm.OP_SHR
	OP_SSHR        Opcode = vm.OP_SSHR
	OP_SHL_C_PRI   Opcode = vm.OP_SHL_C_PRI
	OP_SHL_C_ALT   Opcode = vm.OP_SHL_C_ALT
	OP_SHR_C_PRI   Opcode = vm.OP_SHR_C_PRI
	OP_SHR_C_ALT   Opcode = vm.OP_SHR_C_ALT
	OP_SMUL        Opcode = vm.OP_SMUL
	OP_SDIV        Opcode = vm.OP_SDIV
	OP_SDIV_ALT    Opcode = vm.OP_SDIV_ALT
	OP_UMUL        Opcode = vm.OP_UMUL
	OP_UDIV        Opcode = vm.OP_UDIV
	OP_UDIV_ALT    Opcode = vm.OP_UDIV_ALT
	OP_ADD         Opcode = vm.OP_ADD
	OP_SUB         Opcode = vm.OP_SUB
	OP_SUB_ALT     Opcode = vm.OP_SUB_ALT
	OP_AND         Opcode = vm.OP_AND
	OP_OR          Opcode = vm.OP_OR
	OP_XOR         Opcode = vm.OP_XOR
	OP_NOT         Opcode = vm.OP_NOT
	OP_NEG         Opcode = vm.OP_NEG
	OP_INVERT      Opcode = vm.OP_INVERT
	OP_ADD_C       Opcode = vm.OP_ADD_C
	OP_SMUL_C      Opcode = vm.OP_SMUL_C
	OP_ZERO_PRI    Opcode = vm.OP_ZERO_PRI
	OP_ZERO_ALT    Opcode = vm.OP_ZERO_ALT
	OP_ZERO        Opcode = vm.OP_ZERO
	OP_ZERO_S      Opcode = vm.OP_ZERO_S
	OP_SIGN_PRI    Opcode = vm.OP_SIGN_PRI
	OP_SIGN_ALT    Opcode = vm.OP_SIGN_ALT
	OP_EQ          Opcode = vm.OP_EQ
	OP_NEQ         Opcode = vm.OP_NEQ
	OP_LESS        Opcode = vm.OP_LESS
	OP_LEQ         Opcode = vm.OP_LEQ
	OP_GRTR        Opcode = vm.OP_GRTR
	OP_GEQ         Opcode = vm.OP_GEQ
	OP_SLESS       Opcode = vm.OP_SLESS
	OP_SLEQ        Opcode = vm.OP_SLEQ
	OP_SGRTR       Opcode = vm.OP_SGRTR
	OP_SGEQ        Opcode = vm.OP_SGEQ
	OP_EQ_C_PRI    Opcode = vm.OP_EQ_C_PRI
	OP_EQ_C_ALT    Opcode = vm.OP_EQ_C_ALT
	OP_INC_PRI     Opcode = vm.OP_INC_PRI
	OP_INC_ALT     Opcode = vm.OP_INC_ALT
	OP_INC         Opcode = vm.OP_INC
	OP_INC_S       Opcode = vm.OP_INC_S
	OP_INC_I       Opcode = vm.OP_INC_I
	OP_DEC_PRI     Opcode = vm.OP_DEC_PRI
	OP_DEC_ALT     Opcode = vm.OP_DEC_ALT
	OP_DEC         Opcode = vm.OP_DEC
	OP_DEC_S       Opcode = vm.OP_DEC_S
	OP_DEC_I       Opcode = vm.OP_DEC_I
	OP_MOVS        Opcode = vm.OP_MOVS
	OP_CMPS        Opcode = vm.OP_CMPS
	OP_FILL        Opcode = vm.OP_FILL
	OP_HALT        Opcode = vm.OP_HALT
	OP_BOUNDS      Opcode = vm.OP_BOUNDS
	OP_SYSREQ_PRI  Opcode = vm.OP_SYSREQ_PRI
	OP_SYSREQ_C    Opcode = vm.OP_SYSREQ_C
	OP_FILE        Opcode = vm.OP_FILE
	OP_LINE        Opcode = vm.OP_LINE
	OP_SYMBOL      Opcode = vm.OP_SYMBOL
	OP_SRANGE      Opcode = vm.OP_SRANGE
	OP_JUMP_PRI    Opcode = vm.OP_JUMP_PRI
	OP_SWITCH      Opcode = vm.OP_SWITCH
	OP_CASETBL     Opcode = vm.OP_CASETBL
	OP_SWAP_PRI    Opcode = vm.OP_SWAP_PRI
	OP_SWAP_ALT    Opcode = vm.OP_SWAP_ALT
	OP_PUSH_ADR    Opcode = vm.OP_PUSH_ADR
	OP_NOP         Opcode = vm.OP_NOP
	OP_SYSREQ_N    Opcode = vm.OP_SYSREQ_N
	OP_SYMTAG      Opcode = vm.OP_SYMTAG
	OP_BREAK       Opcode = vm.OP_BREAK
	OP_PUSH2_C     Opcode = vm.OP_PUSH2_C
	OP_PUSH2       Opcode = vm.OP_PUSH2
	OP_PUSH2_S     Opcode = vm.OP_PUSH2_S
	OP_PUSH2_ADR   Opcode = vm.OP_PUSH2_ADR
	OP_PUSH3_C     Opcode = vm.OP_PUSH3_C
	OP_PUSH3       Opcode = vm.OP_PUSH3
	OP_PUSH3_S     Opcode = vm.OP_PUSH3_S
	OP_PUSH3_ADR   Opcode = vm.OP_PUSH3_ADR
	OP_PUSH4_C     Opcode = vm.OP_PUSH4_C
	OP_PUSH4       Opcode = vm.OP_PUSH4
	OP_PUSH4_S     Opcode = vm.OP_PUSH4_S
	OP_PUSH4_ADR   Opcode = vm.OP_PUSH4_ADR
	OP_PUSH5_C     Opcode = vm.OP_PUSH5_C
	OP_PUSH5       Opcode = vm.OP_PUSH5
	OP_PUSH5_S     Opcode = vm.OP_PUSH5_S
	OP_PUSH5_ADR   Opcode = vm.OP_PUSH5_ADR
	OP_LOAD_BOTH   Opcode = vm.OP_LOAD_BOTH
	OP_LOAD_S_BOTH Opcode = vm.OP_LOAD_S_BOTH
	OP_CONST       Opcode = vm.OP_CONST
	OP_CONST_S     Opcode = vm.OP_CONST_S
	OP_NUM_OPCODES Opcode = vm.OP_NUM_OPCODES
)

type OpcodeInfo

type OpcodeInfo struct {
	Name       string
	ParamCount int
	CaseTable  bool
}

OpcodeInfo describes an instruction's encoded name and operands.

func OpcodeMetadata

func OpcodeMetadata(op Opcode) (OpcodeInfo, bool)

type Public

type Public struct {
	Index int
	Name  string
}

type PublicVar

type PublicVar struct {
	Index   int
	Name    string
	Address Cell
}

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

func LoadBytes

func LoadBytes(name string, data []byte) (*Runtime, error)

func LoadFile

func LoadFile(path string) (*Runtime, error)

func (*Runtime) Allot

func (r *Runtime) Allot(cells int) (Cell, error)

func (*Runtime) AllotCells

func (r *Runtime) AllotCells(values []Cell) (Cell, error)

func (*Runtime) AllotString

func (r *Runtime) AllotString(value string, packed bool) (Cell, error)

func (*Runtime) Clone

func (r *Runtime) Clone() *Runtime

func (*Runtime) Close

func (r *Runtime) Close() error

func (*Runtime) Continue

func (r *Runtime) Continue() (Cell, error)

func (*Runtime) DebugInfo

func (r *Runtime) DebugInfo() DebugInfo

func (*Runtime) DebugLocation added in v1.1.0

func (r *Runtime) DebugLocation(address Cell) (file string, line int, function string, ok bool)

DebugLocation resolves an instruction address to available source metadata.

func (*Runtime) Decode

func (r *Runtime) Decode() ([]Instruction, error)

func (*Runtime) ExecMain

func (r *Runtime) ExecMain(args ...Cell) (Cell, error)

func (*Runtime) ExecPublic

func (r *Runtime) ExecPublic(index int, args ...Cell) (Cell, error)

func (*Runtime) ExecPublicByName

func (r *Runtime) ExecPublicByName(name string, args ...Cell) (Cell, error)

func (*Runtime) FindNative

func (r *Runtime) FindNative(name string) (Native, bool)

func (*Runtime) FindPubVar

func (r *Runtime) FindPubVar(name string) (PublicVar, bool)

func (*Runtime) FindPublic

func (r *Runtime) FindPublic(name string) (Public, bool)

func (*Runtime) FindTag

func (r *Runtime) FindTag(id Cell) (Tag, bool)

func (*Runtime) FindTagByName

func (r *Runtime) FindTagByName(name string) (Tag, bool)

func (*Runtime) Info

func (r *Runtime) Info() Info

func (*Runtime) Libraries

func (r *Runtime) Libraries() ([]Library, error)

func (*Runtime) MemoryInfo

func (r *Runtime) MemoryInfo() MemoryInfo

func (*Runtime) Natives

func (r *Runtime) Natives() ([]Native, error)

func (*Runtime) PubVars

func (r *Runtime) PubVars() ([]PublicVar, error)

func (*Runtime) Publics

func (r *Runtime) Publics() ([]Public, error)

func (*Runtime) ReadBytes

func (r *Runtime) ReadBytes(addr Cell, size int) ([]byte, error)

func (*Runtime) ReadCell

func (r *Runtime) ReadCell(addr Cell) (Cell, error)

func (*Runtime) ReadString

func (r *Runtime) ReadString(addr Cell) (string, error)

func (*Runtime) RegisterNative

func (r *Runtime) RegisterNative(name string, fn NativeFunc) error

func (*Runtime) RegisterNatives

func (r *Runtime) RegisterNatives(natives map[string]NativeFunc) error

func (*Runtime) Release

func (r *Runtime) Release(addr Cell) error

func (*Runtime) Reset

func (r *Runtime) Reset() error

func (*Runtime) ResetMemory

func (r *Runtime) ResetMemory() error

func (*Runtime) SetDebugHook

func (r *Runtime) SetDebugHook(hook DebugHook)

func (*Runtime) SetInstructionLimit

func (r *Runtime) SetInstructionLimit(limit int)

SetInstructionLimit sets the maximum instructions for one execution call. Values less than one restore the default limit.

func (*Runtime) SetInstrumentationHook added in v1.1.0

func (r *Runtime) SetInstrumentationHook(hook InstrumentationHook)

func (*Runtime) SetUserData

func (r *Runtime) SetUserData(tag int64, value any)

func (*Runtime) State added in v1.1.0

func (r *Runtime) State() State

State returns the current registers, including the stopped instruction.

func (*Runtime) Suspended

func (r *Runtime) Suspended() bool

func (*Runtime) Tags

func (r *Runtime) Tags() ([]Tag, error)

func (*Runtime) UserData

func (r *Runtime) UserData(tag int64) (any, bool)

func (*Runtime) VM

func (r *Runtime) VM() *vm.VM

VM returns the underlying low-level virtual machine.

Most applications should prefer Runtime's higher-level methods. The VM is exposed for tooling that needs direct access to the bytecode-level API.

func (*Runtime) WriteBytes

func (r *Runtime) WriteBytes(addr Cell, value []byte) error

func (*Runtime) WriteCell

func (r *Runtime) WriteCell(addr Cell, value Cell) error

func (*Runtime) WriteString

func (r *Runtime) WriteString(addr Cell, value string) error

func (*Runtime) WriteStringN

func (r *Runtime) WriteStringN(addr Cell, value string, maxCells int, packed bool) error

type RuntimeError

type RuntimeError struct {
	Code    RuntimeErrorCode
	Message string
	CIP     Cell
}

func (RuntimeError) Error

func (e RuntimeError) Error() string

type RuntimeErrorCode

type RuntimeErrorCode string
const (
	RuntimeErrorBounds       RuntimeErrorCode = "bounds"
	RuntimeErrorDivideByZero RuntimeErrorCode = "divide_by_zero"
	RuntimeErrorHalt         RuntimeErrorCode = "halt"
	RuntimeErrorSleep        RuntimeErrorCode = "sleep"
	RuntimeErrorDomain       RuntimeErrorCode = "domain"
)

type State

type State struct {
	PRI, ALT           Cell
	HEA, STK, STP, FRM Cell
	CIP                int
}

type Tag

type Tag struct {
	Index int
	Name  string
	ID    Cell
}

Directories

Path Synopsis
Package vm exposes the low-level AMX virtual machine.
Package vm exposes the low-level AMX virtual machine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL