ACS File Format
---------------
(All numbers are little-endian and 32 bits long)
(Pointers are relative to the beginning of the lump)

Bytes  0 - 3	'ACS\0' (0x00534341)
Bytes  4 - 7	Pointer to script and text pointers
Bytes  8 -...	Varies

-------------
Pointer Table
-------------
The first dword is a count of the number of scripts in the lump. It is
immediately followed by an entry for each script in the lump. These
entries are of the format:

DWORD 0 This script's number
DWORD 1 A pointer to the start of the script
DWORD 2 The number of parameters the script accepts

These are then followed by a dword indicating how many different strings
are in the script. The remaining dwords contain pointers to each of the
strings.

------------
Script Codes
------------
Compiled ACS scripts do not distinguish between their arguments and
their local variables. When a script is executed, it's parameters
are copied to its first x local variables, where x is the number of
parameters the script takes. The ACC compiler will output an error
for any script with more than 10 local variables (including
parameters), so it's probably safe to allocate enough space for only
10 variables in an ACS interpreter.

There are 64 world variables available (numbered 0-63) that are
accessible from scripts executed from any map in a single hub. Each
map can also have 32 map variables accessible to all scripts in that
map, but not by scripts in other maps.

ACS's internal functions are actually opcodes. Some use arguments on
the stack, and others have their arguments immediately following them
in the code. For those that use arguments on the stack, the arguments
are first pushed on to the stack in sequence, and then the function's
opcode is stored. If the function uses a string as an argument, then
the string's index is pushed onto the stack as a number. Functions
are responsible for popping the arguments passed to them before they
return. The first value pushed is the function's first parameter, the
second value pushed is the second parameter, etc.

  #0:PCD_NOP
  #1:PCD_TERMINATE
  #2:PCD_SUSPEND
  #3:PCD_PUSHNUMBER x
  #4:PCD_LSPEC1 x
  #5:PCD_LSPEC2 x
  #6:PCD_LSPEC3 x
  #7:PCD_LSPEC4 x
  #8:PCD_LSPEC5 x
  #9:PCD_LSPEC1DIRECT x a
 #10:PCD_LSPEC2DIRECT x a b
 #11:PCD_LSPEC3DIRECT x a b c
 #12:PCD_LSPEC4DIRECT x a b c d
 #13:PCD_LSPEC5DIRECT x a b c d e
 #14:PCD_ADD
 #15:PCD_SUBTRACT
 #16:PCD_MULTIPLY
 #17:PCD_DIVIDE
 #18:PCD_MODULUS
 #19:PCD_EQ
 #20:PCD_NE
 #21:PCD_LT
 #22:PCD_GT
 #23:PCD_LE
 #24:PCD_GE
 #25:PCD_ASSIGNSCRIPTVAR x
 #26:PCD_ASSIGNMAPVAR x
 #27:PCD_ASSIGNWORLDVAR x
 #28:PCD_PUSHSCRIPTVAR x
 #29:PCD_PUSHMAPVAR x
 #30:PCD_PUSHWORLDVAR x
 #31:PCD_ADDSCRIPTVAR x
 #32:PCD_ADDMAPVAR x
 #33:PCD_ADDWORLDVAR x
 #34:PCD_SUBSCRIPTVAR x
 #35:PCD_SUBMAPVAR x
 #36:PCD_SUBWORLDVAR x
 #37:PCD_MULSCRIPTVAR x
 #38:PCD_MULMAPVAR x
 #39:PCD_MULWORLDVAR x
 #40:PCD_DIVSCRIPTVAR x
 #41:PCD_DIVMAPVAR x
 #42:PCD_DIVWORLDVAR x
 #43:PCD_MODSCRIPTVAR x
 #44:PCD_MODMAPVAR x
 #45:PCD_MODWORLDVAR x
 #46:PCD_INCSCRIPTVAR x
 #47:PCD_INCMAPVAR x
 #48:PCD_INCWORLDVAR x
 #49:PCD_DECSCRIPTVAR x
 #50:PCD_DECMAPVAR x
 #51:PCD_DECWORLDVAR x
 #52:PCD_GOTO x
 #53:PCD_IFGOTO x
 #54:PCD_DROP
 #55:PCD_DELAY
 #56:PCD_DELAYDIRECT x
 #57:PCD_RANDOM
 #58:PCD_RANDOMDIRECT x y
 #59:PCD_THINGCOUNT
 #60:PCD_THINGCOUNTDIRECT x y
 #61:PCD_TAGWAIT
 #62:PCD_TAGWAITDIRECT x
 #63:PCD_POLYWAIT
 #64:PCD_POLYWAITDIRECT x
 #65:PCD_CHANGEFLOOR
 #66:PCD_CHANGEFLOORDIRECT x y
 #67:PCD_CHANGECEILING
 #68:PCD_CHANGECEILINGDIRECT x y
 #69:PCD_RESTART
 #70:PCD_ANDLOGICAL
 #71:PCD_ORLOGICAL
 #72:PCD_ANDBITWISE
 #73:PCD_ORBITWISE
 #74:PCD_EORBITWISE
 #75:PCD_NEGATELOGICAL
 #76:PCD_LSHIFT
 #77:PCD_RSHIFT
 #78:PCD_UNARYMINUS
 #79:PCD_IFNOTGOTO x
 #80:PCD_LINESIDE
 #81:PCD_SCRIPTWAIT
 #82:PCD_SCRIPTWAITDIRECT x
 #83:PCD_CLEARLINESPECIAL
 #84:PCD_CASEGOTO x y
 #85:PCD_BEGINPRINT
 #86:PCD_ENDPRINT
 #87:PCD_PRINTSTRING
 #88:PCD_PRINTNUMBER
 #89:PCD_PRINTCHARACTER
 #90:PCD_PLAYERCOUNT
 #91:PCD_GAMETYPE
 #92:PCD_GAMESKILL
 #93:PCD_TIMER
 #94:PCD_SECTORSOUND
 #95:PCD_AMBIENTSOUND
 #96:PCD_SOUNDSEQUENCE
 #97:PCD_SETLINETEXTURE
 #98:PCD_SETLINEBLOCKING
 #99:PCD_SETLINESPECIAL
#100:PCD_THINGSOUND
#101:PCD_ENDPRINTBOLD

  #1:PCD_TERMINATE

    Terminates script execution.

  #3:PCD_PUSHNUMBER x

    Push x onto the stack.

  #4:PCD_LSPEC1 x

    Execute line special x. It takes one argument on the stack.
    
  #5:PCD_LSPEC2 x

    Execute line special x. It takes two arguments on the stack.

  #6:PCD_LSPEC3 x

    Execute line special x. It takes three argument on the stack.

  #7:PCD_LSPEC4 x

    Execute line special x. It takes four argument on the stack.

  #8:PCD_LSPEC5 x

    Execute line special x. It takes five argument on the stack.

  #9:PCD_LSPEC1DIRECT x a

    Execute line special x (a).

 #10:PCD_LSPEC2DIRECT x a b

    Execute line special x (a, b).

 #11:PCD_LSPEC3DIRECT x a b c

    Execute line special x (a, b, c).

 #12:PCD_LSPEC4DIRECT x a b c d

    Execute line special x (a, b, c, d).

 #13:PCD_LSPEC5DIRECT x a b c d e

    Execute line special x (a, b, c, d, e).

 #14:PCD_ADD

    Stack before:
	int val1
	int val2

    Stack after:
	int (val1 + val2)

 #15:PCD_SUBTRACT

    Stack before:
	int val1
	int val2

    Stack after:
	int (val1 - val2)

 #16:PCD_MULTIPLY

    Stack before:
	int val1
	int val2

    Stack after:
	int (val1 * val2)

 #17:PCD_DIVIDE

    Stack before:
	int val1
	int val2

    Stack after:
	int (val1 / val2)

 #18:PCD_MODULUS

    Stack before:
	int val1
	int val2

    Stack after:
	int (val1 % val2)

 #19:PCD_EQ

    Stack before:
	int val1
	int val2

    Stack after:
	(val1 == val2)

 #20:PCD_NE

    Stack before:
	int val1
	int val2

    Stack after:
	(val1 != val2)

 #21:PCD_LT

    Stack before:
	int val1
	int val2

    Stack after:
	(val1 < val2)

 #22:PCD_GT

    Stack before:
	int val1
	int val2

    Stack after:
	(val1 > val2)

 #23:PCD_LE

    Stack before:
	int val1
	int val2

    Stack after:
	(val1 <= val2)

 #24:PCD_GE

    Stack before:
	int val1
	int val2

    Stack after:
	(val1 >= val2)

 #25:PCD_ASSIGNSCRIPTVAR x

    Stack before:
	int val

    Store val in script var x.

 #26:PCD_ASSIGNMAPVAR x

    Stack before:
	int val

    Store val in map var x.

 #27:PCD_ASSIGNWORLDVAR x

    Stack before:
	int val

    Store val in world var x.

 #28:PCD_PUSHSCRIPTVAR x

    Push value of script var x onto the stack.

 #29:PCD_PUSHMAPVAR x
    
    Push value of map var x onto the stack.

 #30:PCD_PUSHWORLDVAR x

    Push value of world var x onto the stack.

 #31:PCD_ADDSCRIPTVAR x

    Stack before:
	int val

    script var x += val

 #32:PCD_ADDMAPVAR x

    Stack before:
	int val

    map var x += val

 #33:PCD_ADDWORLDVAR x

    Stack before:
	int val

    world var x += val

 #34:PCD_SUBSCRIPTVAR x

    Stack before:
	int val

    script var x -= val

 #35:PCD_SUBMAPVAR x

    Stack before:
	int val

    map var x -= val

 #36:PCD_SUBWORLDVAR x

    Stack before:
	int val

    world var x -= val

 #37:PCD_MULSCRIPTVAR x

    Stack before:
	int val

    script var x *= val

 #38:PCD_MULMAPVAR x

    Stack before:
	int val

    map var x *= val

 #39:PCD_MULWORLDVAR x

    Stack before:
	int val

    world var x *= val

 #40:PCD_DIVSCRIPTVAR x

    Stack before:
	int val

    script var x /= val

 #41:PCD_DIVMAPVAR x

    Stack before:
	int val

    map var x /= val

 #42:PCD_DIVWORLDVAR x

    Stack before:
	int val

    world var x /= val

 #43:PCD_MODSCRIPTVAR x

    Stack before:
	int val

    script var x %= val

 #44:PCD_MODMAPVAR x

    Stack before:
	int val

    map var x %= val

 #45:PCD_MODWORLDVAR x

    Stack before:
	int val

    world var x %= val

 #46:PCD_INCSCRIPTVAR x

    script var x += 1

 #47:PCD_INCMAPVAR x

    map var x += 1

 #48:PCD_INCWORLDVAR x

    world var x += 1

 #49:PCD_DECSCRIPTVAR x

    script var x -= 1

 #50:PCD_DECMAPVAR x

    map var x -= 1

 #51:PCD_DECWORLDVAR x

    world varx -= 1

 #52:PCD_GOTO x

    Jump to offset x (relative to beginning of object file).

 #53:PCD_IFGOTO x

    Stack before:
	int boolean

    If the boolean is true, jump to offset x.

 #54:PCD_DROP

    Stack before:
	int anything

    Pop one number off the stack and discard it.

 #55:PCD_DELAY

    Stack before:
	int tics

    Pop a number off the stick and delay for that many tics.

 #56:PCD_DELAYDIRECT x

    Delay for x tics.

 #57:PCD_RANDOM

    Stack before:
	int minval
	int maxval

    Stack after:
	int random(minval, maxval)

 #58:PCD_RANDOMDIRECT x y

    Stack after:
	int random(x, y)

 #59:PCD_THINGCOUNT

    Stack before:
	int type
	int tid

    Stack after:
	int thingcount(type,tid)

 #60:PCD_THINGCOUNTDIRECT x y

    Stack after:
	int thingcount(x, y)

 #61:PCD_TAGWAIT

    Stack before:
	int tag

    Pops a tag value off the stack and suspends execution of the current
    script until all sectors with a matching tag value are inactive.

 #62:PCD_TAGWAITDIRECT x

    Waits for all sectors with tag x to become inactive before continuing
    execution of the current script.

 #63:PCD_POLYWAIT

    Stack before:
	int po

    Suspends execution of the current script until polyobj po is inactive.

 #64:PCD_POLYWAITDIRECT x

    Suspends execution of the current script until polyobj x is inactive.

 #65:PCD_CHANGEFLOOR

    Stack before:
	int tag
	str flatname

    Sets the floor flat of all sectors tagged with tag to flatname.

 #66:PCD_CHANGEFLOORDIRECT x y

    Sets the floor flat of all sectors tagged with x to y.

 #67:PCD_CHANGECEILING

    Stack before:
	int tag
	str flatname

    Sets the ceiling flat of all sectors tagged with tag to flatname.

 #68:PCD_CHANGECEILINGDIRECT x y

    Sets the ceiling flat of all sectors tagged with x to y.

 #69:PCD_RESTART

    Restart execution of the current script from the beginning.

 #70:PCD_ANDLOGICAL

    Stack before:
	int boolean1
	int boolean2

    Stack after:
	(boolean1 && boolean2)

 #71:PCD_ORLOGICAL

    Stack before:
	int boolean1
	int boolean2

    Stack after:
	(boolean1 || boolean2)

 #72:PCD_ANDBITWISE

    Stack before:
	int param1
	int param2

    Stack after
	int (param1 & param2)

 #73:PCD_ORBITWISE

    Stack before:
	int param1
	int param2

    Stack after:
	int (param1 | param2)

 #74:PCD_EORBITWISE

    Stack before:
	int param1
	int param2

    Stack after:
	int (param1 ^ param2)

 #75:PCD_NEGATELOGICAL

    Stack before:
	int val

    Stack after:
	int (!val)

 #76:PCD_LSHIFT

    Stack before:
	int a
	int b

    Stack after:
	int (a << b)

 #77:PCD_RSHIFT

    Stack before:
	int a
	int b

    Stack after:
	int (a >> b)

 #78:PCD_UNARYMINUS

    Stack before:
	int val

    Stack after:
	int (-val)

 #79:PCD_IFNOTGOTO x

    Stack before:
	int boolean

    If boolean is false, jump to offset x.

 #80:PCD_LINESIDE

    Stack after:
	int lineside

    lineside is a numerical parameter indicating which side of the line
    activated this script.

 #81:PCD_SCRIPTWAIT

    Stack before:
	int scr

    Suspend execution of the current script until script scr has
    terminated.

 #82:PCD_SCRIPTWAITDIRECT x

    Suspend execution of the current script until script x has
    terminated.

 #83:PCD_CLEARLINESPECIAL

    Clears the special of the activating line.

 #84:PCD_CASEGOTO x y

    Stack before:
	int val

    Stack after:
	int val (if not taken)

    If the val == x, pop it and jump to offset y.

 #85:PCD_BEGINPRINT

    Prepare to build a string to output to the screen by creating a new
    empty working string.

 #86:PCD_ENDPRINT

    Output the current working string to the local machine's screen.

 #87:PCD_PRINTSTRING

    Stack before:
	str string

    Pop a string index off the stack and append it to the current
    working string.

 #88:PCD_PRINTNUMBER

    Stack before:
	int num

    Append num to the current working string in its ASCII representation.

 #89:PCD_PRINTCHARACTER

    Stack before:
	int char

    Append the ASCII character char to the current working string.

 #90:PCD_PLAYERCOUNT

    Stack after:
	int playercount

    playercount is the number of players in the game.

 #91:PCD_GAMETYPE

    Stack after:
	int gametype

    gametype represents the current game type.

 #92:PCD_GAMESKILL

    Stack after:
	int gameskill

    gameskill is the current game skill.

 #93:PCD_TIMER

    Stack after:
	int gametime

    gametime is the current level time in tics.

 #94:PCD_SECTORSOUND

    Stack before:
	str name
	int volume

    Pops two values off the stack and plays a sound in the sector
    pointed at by this script's activating linedef.

 #95:PCD_AMBIENTSOUND

    Stack before:
	str snd
	int vol

    Plays the sound snd at volume vol (0-127) on the local machine.

 #96:PCD_SOUNDSEQUENCE

    Stack before:
	str seq

    Plays the sound sequence seq in the facing sector.

 #97:PCD_SETLINETEXTURE

    Stack before:
	int line
	int side
	int position
	str texturename

 #98:PCD_SETLINEBLOCKING

    Stack before:
	int line
	int blocking

 #99:PCD_SETLINESPECIAL

    Stack before:
	int line
	int special
	int arg1
	int arg2
	int arg3
	int arg4
	int arg5

    Sets the line special and args for all matching lines.

#100:PCD_THINGSOUND

    Stack before:
	int tid
	str name
	int volume

    Plays a sound at all things marked with tid.

#101:PCD_ENDPRINTBOLD

    Print the current working string to the screen of all computers in
    the game.
