The CovertEngine (MW4 engine) documentation
-------------------------------------------

Written by Lasse Öörni (loorni@student.oulu.fi) - August 2002. Any
information is subject to change as the engine is still being developed &
modified. But this information is valid for the MW4 preview.


Contents:

1. Overview

2. CovertEngine coordinate system

3. Chunk-datafiles
3.1 Chunkfile index numbers
3.2 Internal format of a chunk-datafile

4. Actors
4.1 Actor indexes
4.2 Actor type definitions
4.2.1 Complex actor type definition
4.2.2 Simple actor type definitions
4.2.3 Frame definitions for Complex actors
4.3 Actor variables
4.3.1 General variables (for both Complex & Simple actors)
4.3.2 Variables only for Complex actors
4.4 Writing actor move & AI routines

5. Items and weapons
5.1 Item names/Game messages
5.2 Definitions datafile
5.2.1 Weapon definitions
5.2.2 Bullet definitions
5.2.3 Item definitions
5.2.4 Special damage definitions

6. CovertScript quick & dirty reference
6.1 Constants
6.2 Include files
6.3 Variables
6.4 Arrays
6.5 Negative values
6.6 External variables
6.7 Functions
6.8 The pointer parameter
6.9 Data statements
6.10 Stack
6.11 Multithreading
6.12 Paging
6.13 The "act" variable
6.14 How fast is it?
6.15 CovertScript program initialization

7. Triggers
7.1 Defining a trigger
7.2 Removing & redefining triggers
7.3 Trigger types
7.3.1 The T_GAME trigger type
7.3.2 The T_DOOR trigger type
7.3.3 The T_CONV trigger type
7.3.4 The T_NEAR trigger type
7.3.5 The T_PICKUP trigger type
7.3.6 The T_USE trigger type
7.3.7 The T_APPEAR trigger
7.3.8 The T_TAKEDOWN trigger
7.3.9 The T_POSTATTACK trigger
7.3.10 The positional trigger
7.4 Defining new trigger types

8. Background graphics (levels)

9. Music and sound effects
9.1 Music
9.2 Sound effects

10. Files on the game disk

11. Engine ASM function reference
11.1 ACTOR.S
11.1.1 initactors
11.1.2 moveactors
11.1.3 drawactors
11.1.4 depackspr
11.1.5 calcsprdeltas
11.1.6 moveactorx, moveactorxdirect, spawnxmod
11.1.7 moveactory, moveactorydirect, spawnymod
11.1.8 accactorx
11.1.9 accactory
11.1.10 brakeactorx
11.1.11 brakeactory
11.1.12 reverseactor, reversexspeed
11.1.13 checkcollision
11.1.14 checkheadbump
11.1.15 checksideobst, checkjumpobst
11.1.16 turntoup/downstairs
11.1.17 checkstairs, checkstairs_preferup
11.1.18 checklanding
11.1.19 getfreelevelindex
11.1.20 getfreeactor
11.1.21 createactor, initbasicactor, initcomplexactor
11.1.22 getactptr, gap_direct
11.1.23 getactorbyte, setactorbyte
11.1.24 processhealth
11.1.25 spawnactor
11.1.26 removeactor, removelevelactor
11.1.27 removeallactors
11.1.28 followactor
11.2 AI.S
11.2.1 thinker_mammal
11.2.2 gettargetdistance
11.2.3 enemyscore
11.2.4 saynoptr,sayidlenoptr
11.2.5 gointoalert
11.2.6 gototarget
11.2.7 checkdistance
11.2.8 checkwaypoint
11.2.9 makenoise
11.3 CONTROL.S
11.3.1 getcontrols
11.3.2 scankeys
11.3.3 keycontrol
11.3.4 getfireclick
11.4 FILE.S
11.4.1 retryprompt
11.4.2 makefilename
11.4.3 savefile
11.4.4 loadfileretry
11.4.5 loadchunk
11.4.6 loadsprites
11.4.7 closefile
11.4.8 loadallocchunk
11.4.9 purgechunk
11.4.10 getobjectadr
11.5 GAMEMENU.S
11.5.1 menu
11.5.2 exitprogram
11.5.3 loadgame, savegame
11.5.4 drawarrows
11.6 INIT.S
11.6.1 buffertoreu
11.7 ITEM.S
11.7.1 initinventory
11.7.2 finditem
11.7.3 sortinventory
11.7.4 addammo
11.7.5 removeitem
11.7.6 decreaseammo
11.7.7 checkpickup
11.7.8 additem
11.7.9 updatepanel, totalupdatepanel
11.7.10 drawhealthbar
11.7.11 convert8bits, convert16bits
11.7.12 printbcddigit, printbcddigits
11.7.13 setmsgptrs
11.7.14 getitemname, getmsgptr
11.7.15 printmsg, printmsgptr, printmsgcont
11.7.16 ptw_clearrestofrow
11.7.17 ptw_outputchar
11.7.18 printfmttext
11.7.19 resetmsg
11.7.20 cleartextwindow
11.8 KRNDPACK.S
11.8.1 loadfile
11.8.2 getpackedbyte
11.9 KRNLOAD.S
11.9.1 getbyte
11.9.2 openfile
11.10 LEVEL.S
11.10.1 loadlevel
11.10.2 initmap
11.10.3 addactors
11.10.4 addactor
11.10.5 unhideactors
11.11 MATH.S
11.11.1 random
11.11.2 mulu
11.11.3 divu
11.11.4 asr
11.11.5 negate
11.12 PLAYER.S
11.12.1 thinker_player
11.12.2 move_human
11.12.3 move_zsign
11.12.4 move_balloon
11.12.5 spawnballoon
11.12.6 checktriggers
11.12.7 checkdoors
11.12.8 checknpcs
11.12.9 transportplayer, centerplayer
11.13 SCREEN.S
11.13.1 cleartextscreen
11.13.2 updateblock
11.13.3 getcharposinfo
11.13.4 getcharposinfooffset
11.13.5 getcharposinfoxy
11.14 SOUND.S
11.14.1 playsfx
11.14.2 playgametune
11.14.3 togglemusic
11.14.4 playtune
11.15 VM.S
11.15.1 vm_ptrtodatapc
11.15.2 vm_getscriptdatabyte
11.15.3 vm_getscriptbyte
11.15.4 runnextvm
11.15.5 focus
11.15.6 findactorid
11.15.7 settrigger
11.15.8 cleartriggers
11.15.9 spawn
11.15.10 setbit, clearbit, checkbit
11.15.11 vm_getfocus
11.15.12 trigger
11.15.13 getfreevm
11.15.14 stopallvm
11.16 WEAPON.S
11.16.1 loaddefs
11.16.2 attack
11.16.3 attack_human
11.16.4 checkjoydown
11.16.5 move_grenade
11.16.6 move_shuriken
11.16.7 move_meleehit
11.16.8 move_bullet
11.16.9 move_smokecloud, move_gore
11.16.10 weaponanimation
11.16.11 areaeffect
11.16.12 checkbulletcoll
11.16.13 punish, punish_noarmor

12. CovertEngine memory map
12.1 C64 memory map
12.2 Diskdrive memory map (fastloader)

13. Conclusion


1. Overview
-----------

This documentation is more like a reference instead of trying to present a
complete documentation of how the CovertEngine works and how it can be
used. To really see how things are done, you have to dig into the MW4 preview
CovertScript source code, and possibly also the game engine ASM code, but
hopefully this document helps somewhat. Do not expect any more indepth
tutorials - create them yourself after experimenting!

The CovertEngine consists of (roughly in order of execution)

- Bootpart with loader
  * Opens files & reads files byte by byte, until EOF or error
  * Two versions:
    - Autostarting, fastloader - (MW4_FASTLOAD)
    - Non-autostarting, with Kernal loader - (MW4_HARDDISK)
- Depacker
  * Reads a packed data stream from files and return it to caller byte
    by byte
  * Depacker maintains a separate lookback-table (depackbuffer), therefore
    it does not rely on data actually stored into memory
- Loading picture part (will be overwritten by memory pool)
  * Shows the loading picture and load the "engine mainpart",
    and copies the charset and engine init code into place
  * Depacker, loading picture part & engine main part actually exist in
    the same file (EN), stored one after another..
- Engine mainpart, containing:
- Engine init code (will be overwritten by memory pool)
  * Inits variables and state of the several subsystems, and
    then goes into the main loop
  * Among the discardable routines are the REU/SuperRAM file buffering
    routines. These are to be called before anything chunk-datafiles are
    loaded.
- Raster interrupt code
  * Handles scorescreen/gamescreen splits and sprite
    multiplexing, plays music, calls the IRQ-driven scrolling /
    sprite movement (referred as update code from here onwards)
- IRQ-driven update code
  * Scrolls the screen and interpolates movement of sprites
    for 4 screen frames total. While this has been going on, the main
    program has likely prepared the next game frame (4 interpolated
    screen frames). This code is responsible for sprite sorting
    (multiplexing) also, and the actual physical act of moving screen &
    color-RAM data around.
- Input (control) routines
  * Reads joystick & keyboard, and the keyboard-based "pseudo-joystick"
    (keys QWEADZXC + Shift)
- "Highlevel" file routines & memory allocator
  * Allocates, loads & purges chunk-datafiles
  * Provides support for loading of either unpacked or packed files into
    whatever memory address, with retry dialog on error
  * Provides file save support
- Screen support routines
  * Provides background collision detection and possibility to update
    map-data in a controlled manner (changes both in the map and
    on-screen if necessary)
- Actor routines & support routines
  * Updates the spritetables based on actors on screen, handles on-demand
    loading of sprite chunkfiles. Handles movement, landing check for
    jumping/flying actors, obstacle checking etc.
- The actual actor AI & movement code
  * Handles the highlevel decision making and lowlevel movement
    (movement, collisions, animation) of an actor. By default, MW4 has
    a quite complex "human" actor and several less complex actors for
    items, bullets, explosions etc.
  * Also, weapon attack & attack support (reloading etc.) code
- Level routines
  * Loads level graphics & information of actors contained in a level
    (leveldata), and adds actors from the leveldata onto screen while
    the game is running.
- Item routines
  * Handles player inventory, picking up items, losing/gaining ammunition etc.
    Also, scorepanel-update routines and text printing routines reside in this
    module.
- Game menu routines
  * Handles triggering of the game menu script when firebutton has been
    held for a sufficiently long time, and provides support for some
    functions that can not be done in script without some assistance, for
    example loading a saved game or resetting the C64.

and last but not least

- The CovertScript virtual machine(s)
  * Handles the execution of CovertScript bytecode, manages spawning of
    script threads and running of trigger scripts, and pages in bytecode
    from the disk as necessary (using "page faults")

So, the CovertEngine is fairly complex. However, the good thing is that
you do not need to understand much of the low-level components (loader,
raster interrupts, IRQ-driven screen update code, even the virtual machine)
to utilize the CovertEngine.


2. CovertEngine coordinate system
---------------------------------

CovertEngine uses 16 bits for tracking actor positions within the current level.
The system used is following: (Same as in MW3 and BOFH:Servers under Siege)

	Highbyte Lowbyte
        15 ... 8 7 .... 0
        bbbbbbbb pppppsss

The high byte of a coordinate is measured in blocks from the left (or top)
edge of the map, starting from 0. This means that a map can be max. 256
blocks in size, and actually for Y-coords the limit is 128 blocks, for
reasons discussed later.

The 5 most significant bits of the low byte of a coordinate are the
displacement from the left (or top) edge of the block in pixels.

The 3 least significant bits of the low byte are for subpixel accuracy.

Therefore, a coordinate of 0x0380 would mean being in the center of the
4th block measured from the map edge.


3. Chunk-datafiles
------------------

Several forms of data in CovertEngine (blocks, maps, sprites, sound effects,
actor definitions) are in the form of a chunk-datafile and are allocated
dynamically from the memory pool when loaded. The sprite,block,map-chunkfiles
are saved into that format by default by the editor programs, but for others
you will need to construct chunkfiles yourself. The Covertscript compiler aids in
this.

A chunk-datafile has several objects from 0 to n; they are addressed by a 16bit
pointers located before the actual data. The file also stores the total
datasize (including pointers) and number of objects.

To compile a chunk-datafile, invoke

  cs <infile> -o<outfile> -e<externfile, if required> -h

The infile should contain chunk statements:

  chunk( <OBJECT_NUM> )
  {
    byte1, byte2, byte3, ...
  }

Look at MW4SOUND.CS for an example (sound effect definitions)

No object numbers between 0-n may be left undefined, but they need not be
defined in numeric order. Instead, the order in which they are defined
defines the order they appear in memory.

3.1 Chunkfile index numbers
---------------------------

By default, up to 32 chunks can be in memory at once. This is controlled by
the very first define in DEFINE.S. The default chunk indexes are:

  0     Sound effects
  1     Actor definitions
  2     Frame definitions for Complex actors
  3     WEAPON spritefile
  4     ITEM spritefile
  5-29  Other spritefiles
  30    Level map data
  31    Level block data

These (except for the leveldata chunks) map directly to the files C0, C1, C2
etc. on the game disk, when using the LOADCHUNK routine to load. By using
LOADALLOCCHUNK and defining the filename yourself, any filename can be loaded
as a chunkfile (for example the level loading routines do this)

Note that if the memory pool runs out, the "other" spritefiles 5-29 will be
purged as necessary. They are automatically reloaded (by DRAWACTORS routine)
when sprite images from them are needed.


3.2 Internal format of a chunk-datafile
---------------------------------------

(You really do not need to know this, unless you write your own editors for
some unknown type of chunkfile, but anyway...)

Header:
<byte>  Number of objects in the chunk-datafile
<word>  Amount of data in the chunk-datafile (file length-3). This is in
        *high endian* format for loading routine optimization!

Data section:
<words> Pointers to object data for each object, starting from object 0,
        relative to the beginning of the data section. In low endian format.
<?>     Object data

Note that the "level map" chunkfile has actually the map X & Y size prepended
before the chunk header :)


4. Actors
---------

The actors are perhaps the single most important part of the CovertEngine,
as without them there would be no Agents or other characters onscreen, no
bullets flying etc.

4.1 Actor indexes
-----------------

Actor indexes represent the "reservation numbers" for actors currently
active (onscreen). MW4 supports 20 actors, the index numbers are (note
that some ranges overlap intentionally)

	0	Player actor (Agent)
	1-7	Non-player characters (Friendlies, enemies, automated
                security systems)
	6-9     Items to be picked up
	10-13   Player's bullets
	14-18   NPC bullets
        17-19   Particle effects, 19 being used for the actors' speech
                balloons

Actor variables are always indexed through this actor index. Look at
ACTOR.S for symbolic names of these indexes, it makes code a little bit
easer to understand. Also, if you need more actors onscreen, you can
increase these indexes and the total maximum number of actors in DEFINE.S.

4.2 Actor type definitions
--------------------------

The CovertEngine can have up to 128 actor type definitions at any one time.
Actor definitions are actually loaded from disk as a chunk-datafile so for
example different levels can have their own actor-definitions.

There exist 2 kinds of actors: Complex & Simple. These are in a way tied
to the actor indexes. A Complex actor can only have an index from 0-7,
this means the player character and NPCs. For memory saving, actor indexes 8-19
do not have certain variables associated only with Complex actors, and can
therefore contain only Simple actors. The define MAXCOMPLEXACT in DEFINE.S
dictates where this division within the actor indexes occurs.

4.2.1 Complex actor type definition
-----------------------------------

Complex actor types can consist of 2 parts for animation (for example: upper
and lower bodypart), and they can have any number of sprites (total maximum of
sprites is 24) in these parts. Complex actors always need frame-definitions,
that are also stored in a different chunk-datafile.

The actor type definition for a complex actor is like this, using the
AGENT actor from the preview as an example:

All actor type definitions (both complex & simple) start with an AI routine
and move routine addresses. If AI is not to be used, its address must be
0 (to achieve this in CovertScript, you have to type 0,0)

  thinker_player,                   // AI routine address (16bits)
  move_human,                       // Move routine address (16bits)

Next comes the actor's display bitmask. It's an important way of
telling how the actor is shown, and one bit distinguishes between
complex & simple actors. All the bits are defined in ACTOR.S:
ADB_WEAPON - actor has a weapon sprite that is to be drawn after the
second part (upper bodypart for humans)
ADB_SIMPLE - is a simple actor
ADB_INVISIBLE - actor is completely invisible; no sprites are drawn
ADB_FLICKER - actor is drawn each second frame

  ADB_WEAPON,                       // Display bits

Next come the size definitions of the actor. These are measured in chars
(8 pixels) from the actor's coordinates. There are separate heights for
standing upright and ducking.

  1,                                // Size left/right
  0,                                // Size down
  5,                                // Size up
  3,                                // Size up (ducking)

Next, the spritefile chunk number, color override, and frame definition
index for the first part (for humanlike actors, legs). If color override
is 0 the sprite default colors will be used, otherwise all sprites of the
part will be of the override color.

  C_AGENT,                          // 1st part spritefile
  0,                                // 1st part color override
  FR_PLRLEGS,                       // 1st part frame

Same definitions for the second part (humanlike actors' torso).

  C_AGENT,                          // 2nd part spritefile
  0,                                // 2nd part color override
  FR_PLRTORSO,                      // 2nd part frame

Next, the actor's movement capability bitmask.
ACB_WALK - actor can walk on ground
ACB_JUMP - actor can jump
ACB_DUCK - actor can crouch
ACB_CLIMB - actor can climb ladders
ACB_WALLFLIP - actor can flip off walls (joystick to diagonally opposite
directing when hitting wall)
ACB_LONGJUMP - actor can defy gravity during jump ascending phase to
some extent by holding jump button (joystick up for the player character)
ACB_TALL - actor will duck automatically when crawling in ventilation
shafts :)

                                    // Capabilities
  ACB_WALK|ACB_DUCK|ACB_JUMP|ACB_CLIMB|ACB_WALLFLIP|ACB_TALL|ACB_LONGJUMP,

Next, the combat capabilities bitmask.
AFB_ORGANIC - actor is organic (bleeds and is registered as a "kill" when
eliminated using lethal damage)
AFB_INVINCIBLE - actor's hitpoints are never reduced by damage
AFB_DISAPPEAR - actor's body will disappear after elimination
AFB_HEAVY - actor will receive no impulse from weapons/explosions
AFB_REACTNOISE - noises emitted by enemy groups cause actor to go into
ALERT state
AFB_REACTVISUAL - sight of an enemy group member causes the actor to
attack
AFB_REACTBODIES - sight of a body (of own group) causes the actor to go
into ALERT state

                                    // Fighting bits
  AFB_ORGANIC,

Then, a series of speeds. These are in the CovertEngine coordinate system.
Also, note that a game frame lasts 4 screen frames (framerate 12.5 Hz) so
the speeds have to be fairly high. The jump initial speed is always upwards.

  64,                               // Walking speed
  -72,                              // Jump initial speed
  32,                               // Duckwalk speed
  128,                              // Climbing speed

Some X-speed accelerations

  16,                               // Acceleration on ground
  8,                                // Acceleration in air
  16,                               // Braking

Then, the attack position base X & Y modifications. Attack modification
means the value that is added to actor's position to get a position for
the bullet that is being spawned in an attack. These values are in pixels!

  0,                                // Attack X-mod
  29,                               // Normal attack Y-mod
  20,                               // Ducking attack Y-mod

Default armor & hitpoints. As long as there is armor, armor takes 2/3 of
all the damage that an actor receives.

  PLR_MAXBATT,                      // Default armor level
  PLR_MAXHP,                        // Default hitpoints

Patrol radius in blocks. This defines how far away the actor will detect
noises, and react to visual confirmation of enemy.

  7,                                // Patrol radius

Patrol idle time in game frames - how long the actor will randomly stand
still when in the PATROL state. A random modifier of 0-31 will be added
to this time.

  25,                               // Patrol idle time

Various probabilities. The idea of these is that for checking an action, a
random number between 0-255 is generated. If it is below the probability,
the action will be carried out. Except for ducking & ducking exit
probability, these will be carried out if the random number is in the
range (probability, ... , 255). You have to test for yourself what kind of
values lead into a behaviour that you consider reasonable.

  0x0c,                             // Attack probability
  0x60,                             // Melee attack probability
  0xf0,                             // Ducking probability
  0xfd,                             // Ducking exit prob.
  0x40,                             // Duck-attack probability
  0xc0,                             // Climb prob. in combat
  0x80,                             // Target change prob.
  0xc0,                             // Turn if far from target
  0x50,                             // Jump instead of duck
  0x07,                             // Patrol idle prob.

The sound number of actor being eliminated

  SFX_TAKEDOWN,                     // Takedown sound

The Y-modification that is applied to the actor upon elimination (in
CovertEngine coordinate units)

  -2*8,                             // Takedown Y-mod

Color that the actor flashes with when it is hit. Normally, this is white.
Note that for X-expanded actors, the color has to be ORed with value 0x10,
to retain X-expansion when flashing.

  F_HIT                             // Hit flashing color


4.2.2 Simple actor type definitions
-----------------------------------

Simple actors can consist of only one sprite, they are always pointlike
in size, and they do not have the definitions necessary for the default AI
routines. However, you could still build your own custom AI routine, that
does not depend on these definitions, for example a bullet that is a homing
missile. We will use the ITEM actor as an example of a Simple actor.

Note that Simple actors can appear in actor indexes 0-7 (complex actor),
because they are a subset of the Complex actor. The converse is not true.

Like Complex actors, Simple actors begin with the AI & move routine
addresses. Here we see that the ITEM has no AI routine.

  0,0,                              // AI routine address
  move_item,                        // Move routine address

Next come the display bits, as with Complex actors. ADB_SIMPLE has to be
set.

  ADB_SIMPLE,                       // Display bits

Then the sprite chunkfile number.

  C_ITEM,                           // Spritefile number

Notice that Simple actors have no color override!

A value to be added to the actor frame if the actor is facing left. If the
actor does not depend on direction, this will be 0.

  0,                                // Left frame add

Then immediately afterwards comes the frame table, listing spriteframe
numbers from within the sprite chunkfile for each actor frame. The simple
actor definition ends here.

  0,                                // None (never visible)
  11,                               // Fists
  0,                                // Baton
  1,                                // Knife
  2,                                // Katana
  3,                                // Shuriken
  8,                                // Grenade
  6,                                // Dart gun
  4,                                // 9mm pistol
  5,                                // 9mm SMG
  7,                                // Shotgun
  10,                               // 9mm ammo
  10,                               // 12 gauge ammo
  10,                               // Darts
  9,                                // First aid kit
  12,                               // Battery
  13                                // Scroll

4.2.3 Frame definitions for Complex actors
------------------------------------------

Frame definitions are also a chunk-datafile, and loaded from disk. There
can be a maximum of 128 frame definitions in memory at once, and each
frame definition may not exceed 256 bytes. The format of a frame definition
is fairly simple, we will use the AGENT's lower & upper bodyparts as an
example.

This is the FR_PLRLEGS (first part of AGENT actor) frame definition. It
starts with the amount of sprites in this part. If a part has multiple
sprites,  they are all drawn connected to the previous sprite's connect
spot. Also, the first sprite of the second part will be connected to the
last sprite of the first part.

  1,                                 // Amount of sprites

Next is the total amount of frames. This is in fact only needed for
multi-sprite parts, the point is to enable the drawroutine to move on to
the sprite frames for the next sprite.

  44,                                // Amount of frames

The value that is added to the frame if actor is facing left.

  22,                                // Left frame add

Continue flag. If an actor has a second part, this should be nonzero.
Never set the continue flag on the frame definition of the second part, or
the drawroutine will be stuck in an endless loop!

  1,                                 // Continue flag

Then come all the frame numbers for the first sprite. If there is
multiple sprites, their frame definitions will come after the first, in
order.

  29,30,31,32,30,31,32,36,37,38,33,34,35,41,42,41,42,36,39,40,43,42,
  44,45,46,47,45,46,47,51,52,53,48,49,50,56,57,56,57,51,54,55,58,57

As an another example, the AGENT's second aprt (FR_PLRTORSO). Here you see
the continue flag is 0.

  1,                                 // Amount of sprites
  64,                                // Amount of frames
  32,                                // Left frame add
  0,                                 // Continue flag
  0,1,1,0,2,2,0,3,2,0,3,3,3,11,12,13,12,4,4,5,14,0,
  6,7,8,9,10,21,22,23,24,25,
  15,16,16,15,17,17,15,18,17,15,18,18,18,26,27,28,27,19,19,20,29,15,
  21,22,23,24,25,6,7,8,9,10

4.3 Actor variables
-------------------

All of these are arrays indexed by the actor index. They are the key to each
actor's operation. It's mainly the business of actor move & AI routines to
modify these, however by modifying certain variables within the script you
can make additional behaviours (for example in the MW4 preview, the Ninjas
appearing by jumping through the windows, or the Soke going back to meditation
after dealing with an enemy)

4.3.1 General variables (for both Complex & Simple actors)
----------------------------------------------------------

  actt          - Actor type, referring to one of the actor definitions (0-127,
                  0 means actor inactive)
  actxl         - Actor X position least significant byte (LSB) (position
                  within a block)
  actxh         - Actor X position most significant byte (MSB) (block-position)
                  current level (position within block)
  actxl         - Actor Y position LSB
  actxh         - Actor Y position MSB
  actsizex      - Actor's current X size in chars, this is a speedup for
                  collisions and cached automatically from the actor type
                  definition structure by MOVEACTORS. You do not have to touch
                  this.
  actsizeup     - Actor's current Y size from position upwards, see above
  actsizedown   - Actor's current Y size from position downwards, see above
  actd          - Actor direction. If the 8th bit is 1 (values $80-$ff), is
                  facing left, otherwise right. Other bits do not matter and
                  nothing of their contents should be assumed.
  actsx         - Actor's X speed. It's a 8bit signed value, so actor's maximum
                  speed is a little under 16 pixels.
  actsy         - Actor's Y speed
  actfls        - Actor flashing indicator. If nonzero, the actor's sprite color
                  will be overridden with its value. Remember to take X-
                  expansion into account (if actor uses expanded sprites, must
                  use colors $10-$1f). If negative ($80-$ff), actor will flash
                  between visible & invisible.
  actbits       - Actor bits. These are mainly for identifying movement states:
                  AB_JUMP
                  * 1 if actor is jumping
                  AB_LANDED
                  * 1 if actor has just landed after a jump. Usually zeroed
                    soon after that.
                  AB_HITWALL
                  * 1 if actor has hit a horizontal wall.
                  AB_CLIMB
                  * 1 if actor is climbing.
                  AB_AUTOJUMP
                  * 1 if automatical "jump to avoid fall" maneuver has been
                    requested by the AI routine. Applies only to the "human"
                    movement routine.
                  AB_AUTOTURN
                  * 1 if automatical "turn around to avoid fall" maneuver has
                  been requested by the AI routine. Applies only to the "human"
                  movement routine.
                  AB_AUTOTURNDONE
                  * Set to 1 by the "human" movement routine after an AUTOTURN
                  maneuver has been done.
                  AB_DUCK
                  * 1 if actor is crouching.
  acthitwalld   - The direction in which actor has last hit a horizontal wall.
                  Used by AI routines. 8th bit indicates direction, as with
                  actd.
  actorg        - Actor origin. This is the actor index that spawned this
                  actor, used for example when determining who fired a bullet
  acthp         - Actor hitpoints. Reduced by the PUNISH routine (as of now,
                  only applied with bullet/explosion collisions)
  acttime       - Actor time counter. This may be used by the actor movement
                  routines freely, for example to make a bullet disappear after
                  a set time.
  actgrp        - Actor's group association. See above in the actor type
                  definitions section.
  actfd         - Actor's frame delay. This is a delay counter to be used for
                  animations
  actf1         - Actor part 1 animation frame number. For simple actors, this
                  is the only frame variable that exists.

4.3.2 Variables only for Complex actors
---------------------------------------

  actf2         - Actor part 2 animation frame number.
  actlastladderxh - These 3 variables assist in AI pathfinding.
  actlastgroundyl
  actlastgroundyh
  acttarget     - The target actor index this actor is homing to (either for
                  combat, or to follow). If it is negative, means homing to a
                  waypoint instead.
  actmode       - AI mode of the actor. Currently these modes exist: (apply
                  only for the THINKER_MAMMAL AI routine)
                  M_IDLE
                  * Actor does nothing.
                  M_TURNLEFT
                  * Actor turns to left, and returns to IDLE mode.
                  M_TURNRIGHT
                  * Actor turns to right, and returns to IDLE mode.
                  M_TURNTOTARGET
                  * Actor turns to target (actor or waypoint), and returns to
                    IDLE mode.
                  M_SIT
                  * Actor remains in sitting position.
                  M_ANIM
                  * Actor performs a special animation. This is unimplemented
                    as of yet.
                  M_GOTO
                  * Actor follows another actor or homes to a waypoint, using
                    jumping/climbing if necessary and if capable of doing that.
                  M_SPARSEARCH
                  * Actor searches for another actor of same group, and also
                    in the SPARSEARCH mode. Upon finding such actor, both go
                    into SPAR mode. This was exclusively programmed for the MW4
                    preview, do not know if it is useful in other places. :)
                    Probably useful in HQ/training like settings.
                  M_PATROL
                  * Actor moves around, searching for enemies.
                  M_ALERT
                  * Actor has seen/heard something irritating. Searches now
                    enemies, that are not blocked from view by obstacles, and
                    goes to COMBAT state if such enemy found.
                  M_SPAR
                  * Actor "spars" with another actor of the same group, in fact
                    this is the same as COMBAT but bullets never hurt member of
                    the same group.
                  M_COMBAT
                  * Actor attacks another actor, following & trying to inflict
                    damage.
                  These modes can be freely set from script, for example
                  the TURNLEFT/TURNRIGHT modes exist because just changing the
                  actor's direction from script might be overridden by actor
                  AI/move routines.
  acthomemode   - Pathfinding homing mode.
                  HM_HORIZ
                  * Target actor is on the same level in Y-direction, so
                    tries to follow target in X-direction. If an impassable
                    wall separates the actor & target, will go to FREE mode.
                    If Y-distance grows, will go to VERTICAL mode.
                  HM_VERT
                  * Target actor is on different level in Y-direction, tries
                    tries to get on the same Y-level, using for example stairs,
                    ladders, and dropping down if necessary.
                  HM_FREEDOWN
                  * "Free" mode downwards. Tries to go down whenever possible,
                    not caring of target actor's position. This mode will be
                    randomly exited, or if same X-level with target is reached.
                    back to VERTICAL mode.
                  HM_FREEUP
                  * As above, but tries to go up whenever possible.
  actctrl       - The actor's "virtual joystick" bits. This is used by AI
                  routines to signal control to the actor move routine, and is
                  therefore extremely important! Notice the existence of a
                  JOY_JUMP bit. The player's JUMP control simply maps to the UP
                  direction of the joystick, but AIs may specify UP & JUMP
                  controls separately, for ease of programming.
  actprevctrl   - Various "previous" actor controls. Used by the "human"
  actmovectrl     move routine for certain features
  actclimbctrl  - Used by AI routine to remember climbing direction
  actattklen    - AI attack duration counter (how long "firebutton" is held
                  down)
  actattkd      - Attack delay counter. When this is nonzero, it counts towards
                  zero. Only when it is zero can a new attack be initiated.
  actreload     - Nonzero means actor is reloading weapon. The reloading code
                  is fairly complex and even I do not remember its meanings
                  completely :)
  actfb         - Fighting bits. This is simply a cached value from the actor
                  definition structure, for speed optimization.
  actwf         - Actor weapon frame. This is the frame index into the WEAPON
                  spritefile, to show weapons on actors' hands. Negative values
                  ($80-$ff) mean no weapon.
  actbatt       - Actor battery (armor) level.
  actwpn        - The weapon number that the actor is using. For player, this
                  value is updated from player's inventory.
  actlastdmg    - Actor index who last damaged this actor. Used by the AI
                  routines for "self-defence" attacks.
  actlastdmg2   - Actor ID who last damaged this actor. 8th bit indicates
                  lethal damage, if it is 1
  actid         - This actor's ID. The ID must be betweeen $01-$7f and is
                  typically set in the level editor for NPCs; this provides an
                  unique way of identifying a certain instance of an actor, say
                  for example one guard out of 10 that will actually have
                  useful information (ok, bad example :))
  acthpdelta    - Prolonged damage/healing delta value.
  acthptime     - Prolonged damage/healing time counter. Decremented until
                  zero each time acthpdelta is added to hitpoints.
  actclip       - Ammo remaining in weapon. Nonplayer characters have an
                  infinite amount of clips but they still have to stop to
                  reload. For the player actor, this value is simply mirrored
                  from the player's inventory.

4.4 Writing actor move & AI routines

To create new kind of actor behaviour, you will likely have to write own move &
AI routines in ASM (CovertScript would be much too slow).

The basic idea is that the move-routine of an actor is responsible for all
physics, movement & animation that an actor performs. Without a move routine,
the actor stands completely still on the screen, not even falling as necessary.

The AI routine's task, on the other hand, is to supply the "virtual joystick"
control values to the move routine.

I suggest starting by studying the simplest move routines, like the bullet
& explosion routines. Try to re-use as much of the existing code as possible,
and utilize the actor subroutines to their fullest extent. You can also try
expanding the "human" move & AI routines the way you feel necessary.

Note that by removing/rewriting all sideview-physics related code (falling,
jumping etc.) from the actor routines, you can create a birdseye-view game.
The idea of scrolling and putting/removing actors onscreen remains the same.

Good luck - this is probably the hardest part in using the CovertEngine!


5. Items and weapons
--------------------

Items are the things player actor can pick up and use. The first item numbers
always map to weapons numbers too (these are the only kinds of items that
NPCs can currently use)

For items to work properly several properties have to be defined.

Note: the variable "firstotheritem" distinguishes between weapons & other
items. For the MW4 preview, it is set in MW4INIT.CS


5.1 Item names/Game messages
----------------------------

Item names are part of the indexed message system, used also for miscellaneous
game messages and menu texts. See MW4TEXTS.CS (and MW4INIT.CS) to see how the
message texts/item names are defined by using the setmsgptrs() call. Basically,
it is a bunch of pointers within the script data, each pointing to a text
string.

Also, to define what is the first item name out of all the game messages, you
need to set the variable "firstitemname". This is done in MW4INIT.CS.

A simple example, with just 1 game message (message index 0), and 3 item names
(message indexes 1-3). Note: the first item name is of the item 0, the "empty"
item!

  // The code to init message pointers, and set the index of first item name
  init()
  {
    setmsgptrs(my_msg_ptrs);
    firstitemname = 1;
  }

  // The message pointers
  msgptrs: data(msg_pause, msg_itemname0, msg_itemname1, msg_itemname2);

  // The message strings. The "pause" message also has a message duration
  // before it, but the item names do not need this:
  msg_pause: data(12, "GAME PAUSED",0); <-- duration 12 frames, roughly 1 second
  msg_itemname0: data("EMPTY ITEM",0);  <-- this text never appears :)
  msg_itemname1: data("KATANA",0);
  msg_itemname2: data("NUNCHAKU",0);

5.2 Definitions datafile
------------------------

Weapon/Bullet/Item/Special damage definitions are stored to a datafile of its
own kind, that is not a chunk-datafile, but something else. Look at MW4ITEMS.CS
to see the definitions the MW4 preview uses.

The file consists of 4 sections, in this order:
- Weapon definitions
- Bullet definitions
- Item definitions
- Special damage definitions

Each definition begins by a byte describing what weapon/bullet/item index to
define. The end of a section is marked by inserting $ff (255) in place of this
byte, no actual definition data will follow in that case.

To compile this special kind of datafile, just invoke the CovertScript compiler
with an output-file defined, but without the -h (chunk-datafile header)
parameter:

  cs <infile> -o<outfile> -e<externfile, if required>

5.2.1 Weapon definitions
------------------------

We will take the FISTS weapon from MW4ITEMS.CS as a first example.

We start with the item (remember, first item numbers map directly to weapons)
index we want to define.

  ITEM_FISTS,

The first value is the noise level. This can be 0 (no noise), NOISE_SILENT
(alerts enemies within 3 blocks), NOISE_MODERATE (alerts enemies within 6
blocks) and NOISE_LOUD (alerts all enemies onscreen + sets the "hostile
enviroment" variable because now all enemies in the level have heard the
sound). The effect of the hostile enviroment ("hostileenv") variable is as
follows:
  0 - Level is not yet hostile. Enemy group members do not shoot on sight, and
      do not become alerted by SILENT or MODERATE sounds.
  1 - Level is hostile. Enemies shoot on sight and become alerted by the
      slightest sound.
By setting "hostileenv" to 0 on level init infiltration-style missions can be
made. :)

  0,                 // Noise

Next is the amount of bullet actors spawned per shot. Usually 1. Note that the
comment "ammo consumption" is misleading, because ammunition in clip will
always decrease by 1.

  1,                 // Ammo consumption

The bullet number that is created by firing this weapon. Note for spawning
multiple bullets (the shotgun, for example), the bullet definition contains
a "next bullet" field.

  BLT_FISTHIT,       // First bullet number

Reload parameters can all be 0 for melee weapons, we will look at them again
when we are looking at a firearm.

  0,                 // Reload time (insert new clip)
  0,                 // Reload time (after readying)
  0,                 // Reload amount
  0,                 // Reload sound (insert clip/bullet)
  0,                 // Reload sound (ready weapon)

Weapon frames. This describes what frames from the WEAPON spritefile will be
displayed for various actions. Negative values (like WF_NONE) will not display
a weapon on the actor's hands at all. 1 is automatically added to the frame
if the actor is facing left.

  WF_NONE,           // Idle frame
  WF_NONE,           // Attack prepare frame
  WF_NONE,           // Attack frame (straight)
  WF_NONE,           // Attack frame (up)
  WF_NONE,           // Attack frame (down)

This is nonzero if weapon can also be fired diagonally up or down.

  0,                 // Directional?

This is nonzero if weapon emits a muzzle flash when fired. It automatically
adds 2 to the weapon sprite frame, so weapon sprites will have to be defined
in an order such as:
<without muzzle flash, facing right>
<without muzzle flash, facing left>
<with muzzle flash, facing right>
<with muzzle flash, facing left>
etc.

  0,                 // Muzzle flash?

This indicates whether a melee animation will be displayed when attacking. 0
means no melee animation. A value of 1 shows the weapon hand bent behind the
actor's head (as with a whip, for example) and a value of 2 shows the weapon
arm just pulled backwards (as with fists or knives). During this animation,
the "prepare" frame of the weapon is shown (see above).

  2,                 // Is a melee weapon?

Sound effect played on successful attack.

  SFX_PUNCH,         // Sound effect number

The maximum distance from target actor (in blocks, horizontally) where an AI
controlled actor will still use the weapon.

  2,                 // NPC maximum distance

The minimum distance from target actor (in blocks, horizontally) where an AI
controlled actor will still use the weapon.

  0,                 // NPC minimum distance

How long (in game frames) the AI controlled character keeps the "firebutton"
pressed.

  3,                 // NPC attack time (time firebutton is held down)

How long (in game frames) until the actor can attack again.

  3                  // Attack delay

The weapon definition ends here. Now we will take a look at the PISTOL
definition to see the meaning of the reloading parameters. These first values
need no explanation now:

  ITEM_PISTOL,
  NOISE_LOUD,        // Noise
  1,                 // Ammo consumption
  BLT_9MM,           // First bullet number

Here is the time (in game frames) that is taken to insert a new clip.

  8,                 // Reload time (insert new clip)

And here is the time that passes from inserting a clip before the weapon can
be fired again.

  3,                 // Reload time (after readying)

This is the amount of bullets reloaded at once. Normally this is 255 (it can
be larger than the clip size, it will not cause problems) to make sure the full
clip is reloaded. But some weapons like the shotgun can be made to reload only
one bullet at a time, by setting this to 1.

  255,               // Reload amount

Here are the reload sound effect definitions, for enhancing combat atmosphere :)

  SFX_INSERTCLIP,    // Reload sound (insert clip/bullet)
  SFX_COCKFAST,      // Reload sound (ready weapon)

The rest of the values have already been explained:

  WF_PISTOL,         // Idle frame
  WF_PISTOL+8,       // Attack prepare frame
  WF_PISTOL,         // Attack frame (straight)
  WF_PISTOL+4,       // Attack frame (up)
  WF_PISTOL+8,       // Attack frame (down)
  1,                 // Directional?
  1,                 // Muzzle flash?
  0,                 // Is a melee weapon?
  SFX_PISTOL,        // Sound effect number
  5,                 // NPC maximum distance
  1,                 // NPC minimum distance
  4,                 // NPC attack time (time firebutton is held down)
  4                  // Attack delay

5.2.2 Bullet definitions
------------------------

Likewise, bullet definitions begin with the index of the bullet to be defined.
We will take the 9mm bullet as an example:

  BLT_9MM,

Here are the low & highbyte modifications for the X & Y coordinates of the
bullet. These are in the CovertEngine coordinate system (with subpixel
accuracy). The idea is, that in addition to the actor's attack X & Y
modifications, these are added to get the final starting position for the
bullet.

  24*8 & 0xff,        // X modification lowbyte
  24*8 >> 8,          // X modification highbyte
  (-2*8) & 0xff,      // Y modification lowbyte
  (-2*8) >> 8,        // Y modification highbyte

These are the starting X & Y speed for the bullet. All bullet acceleration
must be handled by bullet actor move routines.

  15*8,               // X speed
  0,                  // Y speed

This is the Y-speed modification for aiming up & down. The idea is that
bullets should go in 22.5 degrees angle up or downwards, so therefore the
Y-modification is the X-speed divided by 2.

  15*8/2,             // Y aiming speed modification

In addition to the aiming speed modification, an Y-position modification
can be applied while aiming, this is to take into account the offset caused
by weapon arm being directed up or downwards.

  12*8,               // Y aiming pos. modification

Next is a flag value describing whether Y-aiming affects bullet animation frame.
In the MW4 preview, this is used with the dart bullets. If aiming up, bullet
start-frame is 1 instead of 0. If aiming down, start-frame is 2.

  0,                  // Y aiming affects bullet frame?

This is the actor type number of the bullet.

  ACT_BULLET,         // Bullet actor number

This is the amount of damage the bullet will produce upon collision. It is
loaded into the acthp variable of the bullet actor.

  DMG_9MM,            // Bullet damage

About damage: the 8th bit defines the damage to be "lethal"; if "lethal"
damage makes the actor's hitpoints go to zero he will "die", otherwise he will
be knocked unconscious. This is a similar system as in Deus Ex, I believe
(instead of separate hitpoints counters for "lethal" & "nonlethal" damage).

Values $70-$7f in the damage will denote "special" damage; for example value
$70 uses special damage index 0. More of this below..

The value that will be loaded to acttime variable of the bullet actor,
typically the time in game-frames the bullet will travel before disappearing
automatically.

  10,                 // Bullet duration

Last comes the next-bullet indicator. If it is zero, no further bullets will
be spawned. If nonzero, it indicates the bullet index of the next bullet. Note
a slight design flaw: because bullet index 0 is actually the FISTHIT bullet in
the preview, it means that it can never be a "next bullet". This can be avoided
by starting bullet definitions from 1, or perhaps modifying the engine to use
negative value instead to mean "no next bullet". :)

  0                   // Next bullet (multi-bullet weapons)

5.2.3 Item definitions
----------------------

These are definitions common to both weapons and other items, like maximum
inventory amount that can be carried and default pickup amount. Also the ammo
type of a weapon will be defined here. We will take a look at the PISTOL &
9MMAMMO definitions, to understand the relationship between them:

PISTOL definition:

  ITEM_PISTOL,
  15,                  // Default pickup amount
  15 & 0xff,           // Maximum carried lowbyte
  15 >> 8,             // Maximum carried highbyte
  ITEM_9MMAMMO         // Ammo item type

9MMAMMO definition:

  ITEM_9MMAMMO,
  50,                  // Default pickup amount
  300 & 0xff,          // Maximum carried lowbyte
  300 >> 8,            // Maximum carried highbyte
  AMMO_NONE            // Ammo item type

We see that the pistol's clip size is 15, and always when a pistol is picked
up, it is assumed to have the full clip's worth of ammunition. The pistol is
defined to use the 9MMAMMO item for reloading (reloading practically means
transferring item count from the "ammo" item to the "weapon" item)

The 9mm ammo on the other hand has a higher default pickup value (if an ammo
box is found), maximum carried amount of 300 and has no item that can be used
for reloading, this makes sense? :)

If an item has AMMO_NONE set for ammo item type, it means that the item will
disappear from inventory once the count is depleted (grenades, shurikens,
medikits etc.) but weapons like pistols will not disappear, because they can
be reloaded.

There is also one more possible value for the ammo item type, and that's
AMMO_INFINITE. This is used for the melee weapons.

5.2.4 Special damage definitions
--------------------------------

These are an extended form of damage. The MW4 preview defines one type of
"special damage" and that is for the tranquilizer darts:

  SPDMG_DARTS,

Condition that is required for the damage to work. All bits that are defined
here must also be 1 in the actor's fighting bits or the damage is ineffective:

  AFB_ORGANIC,         // Fightbits that must be on for damage to work

The duration & strength of prolonged damage. Hitpoints delta must be negative
unless it is supposed to be some kind of healing effect :) The total damage
will be (time * delta).

  10,                  // Damage time
  -2,                  // Damage hitpoints delta

In addition to the prolonged damage, there can be an initial damage:

  2                    // Initial damage


6. CovertScript quick & dirty reference
---------------------------------------

CovertScript is a C-like language, with standard C-like statements (if, for,
while, switch etc.) and operators included. They should work like their C
counterparts. Some things, like function & variable definitions, are different.

6.1 Constants
-------------

To define constants for later use, use the #define directive. Note: unlike the
C preprocessor directive, this only works for assigning a string with a numeric
constant value. The constant must resolve at the time the define is first
encountered. For example

  #define NUM_LEVELS 4

You can use either $ or 0x to mark hexadecimal numbers.

6.2 Include files
-----------------

To include other files, use the #include directive, just like the C
preprocessor directive. Including binary files as data is not currently
supported.

6.3 Variables
-------------

Variables must always be defined outside a function, there are no local
variables (evil). For example

  var lives;

would reserve a variable named lives from the variable area.

6.4 Arrays
----------

To define an array, add [ <arraysize> ] after the variable name. Array size
must resolve to a constant. For example

  var enemies[NUM_LEVELS];

The only supported data type for variables & data is 8-bit unsigned char, so
each variable takes 1 byte, and arrays take <arraysize> bytes.

To reference the indexes of the array, you can then use [ <expression> ] just
like in C. There is no range checking either compile- or runtime. Array indexes
start from 0.

Note that you can not use the index 255 of an array! A write to index 255 will
be skipped and read from index 255 will always return a 0. This is a feature
of the CovertScript virtual machine as implemented in the CovertEngine, index
255 is used to mark "nonexistent actor".

6.5 Negative values
-------------------

You are free to use negative values for constants & variables but remember that
< and > do not work correctly with negative numbers, as they assume unsigned
comparisions. So to check for a variable being negative, you have to type

  if (n & 0x80) instead of
  if (n < 0)

6.6 External variables
----------------------

To use external variables (defined in your ASM code), you must have an
extern-definition file (tell with the -e switch to CS compiler, what file to
use). The extern-definition file should follow this format (just an example)

  symbol1 = $5675
  symbol2 = $8762

To produce an extern-file from a DASM generated symboltable, run SYMBOLS.EXE
with just 2 parameters: SYMBOLS <symboltablefile> <extern-file>. you will see
that the CovertEngine makefile does just this to generate an extern-file out of
all symbols that the CovertEngine defines.

Then in your CovertScript code, you can write:

  extern var symbol1; or just
  extern symbol1;

To define an external array, just add [] after the variable name; however this
is only to remind you it is an array, the compiler does not mind it.

6.7 Functions
-------------

Functions is where CovertScript differs most from C. CovertScript requires no
function prototypes. Instead, you just type:

  <functionname> <optional returnparameter> ( <parameters> )
  {
    ...function body code...
  }

to define a function. To define an external (ASM) function in the game engine,
just type

  extern <functionname> <optional returnparameter> ( <parameters> );

Note that the return parameter & source parameters go always to the explicitly
defined variables (no parameter passing in the stack). This can create
problems if you want to nest functions.

There exist the pre-defined variables "a","x","y" and "flags". These are for
parameter passing to/from external functions. Note that the variables "a","x",
"y","act" and "flags" are (more on "act" later) unique for each thread.

a,x,y reflect the CPU registers, that are loaded upon the external function
call. Flags will return the status of the CARRY flag upon return from the
external function.

Note that the registers are not automatically reflected back to variables a,x,y
upon return from the external function, only one of them can be returned as a
return value. For example, the getfreeactor() function of the CovertEngine
would be defined as

  extern getfreeactor y(y,a);

In this case, "y" will be assigned the first parameter and a with the second.
The return variable "y" will reflect the CPU "y" register after the call (this
routine also returns error information in "flags", but look at the engine ASM
function reference to see what the function does exactly).

CovertScript gives quite a bit of freedom in using the functions, you may
always call a function with no parameters if you know the parameter variables
already contain suitable values.

In your own functions, you can use the return statement (as in C) to assign
a value to the return variable, or just return; to return with no assignment
performed. For example, if the return variable is "a",

  return(5); will be equivalent to a = 5; return;

Because there is no stack manipulation involved in functions, you may "goto"
freely from function to another. This is great for games in my opinion; I
always found C clumsy in the respect of program flow (for example) from game
title screen to game initialization & main loop, because it is strictly based
on function calls.

6.8 The pointer parameter
-------------------------

Some functions like the text printing functions require a pointer parameter to
the script data. This is specified by "ptr" in the parameter list. The pointer
parameter has to be constant. What this pointer-parameter really does is to

  load "y" with the low byte of address (bits 0-7)
  load "x" with the middle byte of address (bits 8-15)
  load "a" with the high byte of address (bits 16-23)

You can also explicitly do a loadptr( <labelname> ); by yourself.

6.9 Data statements
-------------------

You can use the statement

  data(byte1, byte2, byte3, ... );

to define data in the script address space. This is only valid outside a
function. You can also define string data with quotation marks. To be useful,
the data statement is often accompanied by a label, for example:

enemies_on_level:
  data(100,150,200,250);

Then you could reference enemies_on_level[] like an array, just remember it is
read-only like all script data.

Alternatively, you can also type a shorthand form
  {byte1, byte2, byte3, ... }

Note that a data statement can also be passed directly to a function that
expects a pointer parameter, for example

  say({BARK_TIME, 34, "Agents and Ninjas have a lot in common", 34, 0});

All the data statements defined this way will be generated after the function
body code in the script address space.

If you reference an external identifier within a data statement, it will
translate into a 16bit pointer. If you reference a script label within a data
statement, it translates into a 24bit pointer (see "mw4text.cs" for an example
of using this.)

6.10 Stack
----------

The virtual machine architecture of CovertScript is stack-based. By default 32
bytes of stack are given to each execution thread. A function call will take 3
bytes of (a 24-bit return address) and arithmetic operations like + - / * take
2 bytes during their evaluation. An indirection takes one byte. So if you nest
function calls too much or make your expressions/indirections too complex, you
might overflow the stack.

To see if you overflow the stack, set VM_STACKDEBUG to 1 in the file VM.S
and recompile the engine. The border will turn yellow if it overflows.

You can also increase the stack size in the file DEFINE.S, but note that
the combined stack space for all threads may not exceed 256 bytes.

6.11 Multithreading
-------------------

Currently the CovertEngine supports 4 threads at the same time (defined in
DEFINE.S). They each have a stack of their own and unique a,x,y,flags & act
variables. The rest of the memory is shared between all of them.

To start a new thread at a label or function, issue the function call

  spawn( <label or function> );

To stop the current thread, issue the statement

  stop(); or
  stop;

To stop all other threads, issue the function call

  stopallvm();

The engine uses a cooperative multitasking model. Therefore you can be sure
that no operation is interrupted unless you explicitly allow it. To yield the
control from the current thread, issue the function call

  release();

Note that if you have a thread doing calculations with no release() at all, the
game appears frozen. If you look at the CovertScript code included with the
preview, you will see that release() is used in all waiting-functions, and in
the menu/conversation multichoice functions.

A visible example of multithreading are the title screen texts: you may
activate the game menu and they still keep going. The menu and title screen
loops run in separate threads.

6.12 Paging
-----------

The CovertScript bytecode is paged in from the disk in 2 KB blocks or "pages".
The first page ($000000-$0007ff in script address space) will never be paged
out after it has been loaded, so it can contain common functions & data used
throughout the program.

Note that running multiple threads away from each other in the script address
space can result in horrible disk thrashing, because by default only 2 other
pages are kept in memory (a total of 6 KB allocated to pages)

Pages are read-only; you will get a compiler error if you try to modify script
data.

6.13 The "act" variable
-----------------------

In the CovertEngine, actors get added/removed onscreen as the player moves to
different locations. An actor is created to a free actor index; you can not
know what actor is currently in what index, and even if you knew, would it be
there on the next frame?

Instead the engine offers actor IDs, the focus() call and the "act" variable to
make this easier. An example from the MW4 preview: the "boss enemy" at the
secret cave has an unique id of ID_MASTERNINJA (set with AOMEDIT, the
background editor). Now, to access the properties of just that actor, we do

  focus(ID_MASTERNINJA);

After this, the variable act will reflect the actor index of the Masterninja,
or 255 if the ninja is not onscreen. This is why array index 255 is unusable
for reads/writes.

You may wonder where that value you set with focus() goes. It goes directly to
the VM internal variables, but to access it you can use

  vmfocus[vmnum]

after you first define the vmfocus external array with

  extern var vmfocus[];

(for safety reasons it is not defined in MW4EXT.CS by default)

Using focus() adds a small overhead to the execution of a thread. To revert to
the default mode of no focus, use

  focus(ID_NONE);

6.14 How fast is it?
--------------------

Execution of one CovertScript virtual machine instruction takes something
between 2-6 rasterlines, so it is not blindingly fast at all. Instructions do
relatively small things, for example the assignment

  a = x;

translates into:

  pushv $01
  storev $00

An addition

  a = x + y;

translates into

  pushv $02
  pushv $01
  add
  storev $00

CovertScript is at its best when it is not running at all :) This is not a
contradictory statement or meant to insult it, it is just a suggestion to use
trigger code as much as possible, instead of having some thread running in
the background all the time.


6.15 CovertScript program initialization
----------------------------------------

The CovertEngine mostly initializes itself, but initialization of certain
things is left to the script. This is to hardcode as little as possible into
the engine. See MW4INIT.CS for an example of what the MW4 preview does for
initialization:

  - Sets player actor hitpoints & armor to maximum (so that the energy bars
    will display nicely), calls initinventory() and drawpanel() to display
    the initial status panel
  - Buffers datafiles into REU, if REU detected. This is completely optional
  - Sets these variables:
    * firstitemname (message index of first item name)
    * firstotheritem (first item that is not a weapon)
    * firstpurgeablechunk (first sprite-chunk that can be purged)
    * plrmaxbatt (player's maximum armor level, for armor "healing")
  - Sets the game message pointers
  - Initializes MW4's menu system (mainly, this is not a part of the
    CovertEngine but instead MW4's own system)
  - Loads the weapon/bullet/item/specialdamage definition file
  - Loads the sound effects, actor definitions, and frame definitions
    chunk-datafiles
  - Loads the WEAPON, COMMON & ITEM-spritefiles. The WEAPON spritefile
    will not be automatically loaded (as the weapons really aren't part of
    any actor), so this is important. COMMON & ITEM spritefiles would be
    loaded (because regular actors use them), but it's nice to precache them.
  - Sets the menu trigger routine (type: T_GAME ID: G_MENU) which will activate
    when player holds firebutton down for about 1/2 seconds.


7. Triggers
-----------

Triggers are, in addition to actors, another very important part of the
CovertEngine. By using triggers, CovertScript code is only executed when
necessary (when a certain event happens); this reduces the need to have
CovertScript code running all the time, polling for the event to happen.

7.1 Defining a trigger
----------------------

To define a trigger, execute this function call in CovertScript code:

  settrigger(pointer_to_datastatement);

Ok, that does not really say much. The data statement used be settrigger() is:

  {trigger_type,
   trigger_id,
   function_to_call}

Trigger type is the "main class" of the trigger event (conversation, item
pickup, actor appearing etc).

Trigger ID is a "parameter" that helps in identifying what exactly caused the
trigger. For actor related triggers, this is the actor ID, for items, this is
the item number etc.

Function to call is simply the CovertScript function that will be executed
on the trigger event happening. Upon calling, the "a" variable (reflecting the
A register of the 6510) will contain the trigger ID. For actor triggers, the
external variable "c_act" will contain the actor index that caused the trigger
(this is not to be modified!)

If a trigger is defined with ID $ff it will match any ID! This is useful for
creating "default" actions. However, you must be careful with them, you must
first define all the special cases and the "default" case last.

There is a maximum of 64 triggers at once. This can be increased from DEFINE.S
but remember that increasing this amount will make the trigger checks take
a longer time.

7.2 Removing & redefining triggers
----------------------------------

There must also be the ability to remove triggers. The cleartriggers() call
removes all triggers except T_GAME triggers. Typically, a new set of triggers
is set upon level initialization.

Triggers can also be redefined by giving the same type & ID, but different
function, to settrigger().

7.3 Trigger types
-----------------

7.3.1 The T_GAME trigger type
-----------------------------

T_GAME triggers are related to special game actions. There exist two IDs for
this trigger type:

  G_MENU - Whenever the game menu (by holding down firebutton) is to be
           entered. Note that the menu functionality, except activation, is
           entirely handled in CovertScript code!
  G_LOAD - Whenever a game is loaded from the disk. A game save file contains
           everything needed to know of the game status, except one thing:
           modifications made to the current level map. For example, in the
           MW4 preview, the breaking windows and the opening of the secret
           passage. This trigger will allow the map modifications to be
           redone; you must use boolean flags (plotbits) or variables to keep
           track of what you have to do.

7.3.2 The T_DOOR trigger type
-----------------------------

Called whenever a door entry is attempted by player (you could also implement
things like switches or computers to operate by using "doors").
The ID is the door number on the map (0-63).

Because the MW4 preview contains no locked doors, the default door routine
(ID $ff) is simple:

  enterdoor()
  {
    transportplayer();
  }

You could for example check for keys/keycards etc. in the door trigger routine,
and refuse entry as necessary.

7.3.3 The T_CONV trigger type
-----------------------------

Called whenever a conversation with NPC is attempted by player (when player
is sufficiently close to NPC and presses FIRE+UP on joystick). The ID is the
target actor's ID.

7.3.4 The T_NEAR trigger type
-----------------------------

Called whenever player is near a NPC that has a nonzero actor ID. The ID is
naturally the NPC's actor ID.

To prevent congestion of the VM threads from this trigger type, it must be
"reset" upon completion of the T_NEAR trigger code by calling

  neartriggerdone();

before further T_NEAR triggers can happen.

7.3.5 The T_PICKUP trigger type
-------------------------------

Called whenever player picks up an item. The ID is the item type. This will
make it easy to implement things like "the temple starts to collapse when you
pick up the idol from the booby-trapped pedestal" :)

7.3.6 The T_USE trigger type
----------------------------

Called whenever player uses an item, that is not a weapon. The ID is the item
type. This is used to implement the use of medikits and rechargers in the MW4
preview.

7.3.7 The T_APPEAR trigger
--------------------------

Called whenever an actor appears onscreen. The ID is the actor's ID. This
can be used to reset things like AI state, target etc. In the MW4 preview it is
used to ensure that the first student (the one player can spar with) remains
in sparring state even after going off-screen.

7.3.8 The T_TAKEDOWN trigger
----------------------------

Called whenever an actor's hitpoints run out. The ID is the actor's ID. The
main use of this is to make certain enemies drop some other item than the
weapon they are using (default).

7.3.9 The T_POSTATTACK trigger
------------------------------

Called whenever an actor has been in COMBAT or ALERT state but can not find any
more enemies to combat. The ID is the actor's ID. In the MW4 preview, this is
used to make the Soke calm down and go back to meditating after dealing with
the Ninjas. :)

7.3.10 The positional trigger
-----------------------------

Called whenever player crosses a certain position on the map. The use of this
trigger is a bit tricky:

The trigger type is the Y position is blocks, with 8th bit set. The trigger
ID is the X position in blocks.

For example, to set a positional trigger at the location (5,10), you would call

  settrigger({0x8a, 0x05, routine});

7.4 Defining new trigger types
------------------------------

You are absolutely free to invent more trigger types as you feel necessary.
To do this, you must add a call to TRIGGER in the location you wish in the
engine ASM code. For example, to add a new trigger T_ATTACK, that is called
whenever an actor goes into the COMBAT state, you would locate this piece of
code in AI.S:

tmi_gotohate:   lda #M_COMBAT
                sta actmode,x
                lda #HM_HORIZ
                sta acthomemode,x
                lda #$00
                sta actattklen,x
                sec
tmi_stayidle:   rts

and before the SEC instruction, add this:

                stx actrestx            ;TRIGGER overwrites X register, save it
                lda actid,x             ;Get current actor's ID (trigger ID)
                beq tmi_noattacktrigger ;Skip if ID is zero
                ldx #T_ATTACK           ;Trigger type
                jsr trigger             ;Execute trigger function!
tmi_noattacktrigger:
                ldx actrestx            ;Restore X register


8. Background graphics (levels)
-------------------------------

Levels in the CovertEngine consist of: Charset, Blocks, Map, Char-info, Char-
colors, Actor positions & other definitions, Door definitions and Zone
definitions. The editor AOMEDIT is used to modify all of these (see its
separate documentation within the C64-utility collection)

8.1 Charset

255 chars can be used, in multicolor character mode. (The 256th char contains
interrupt vectors at the bottom of memory)

8.2 Blocks

Backgrounds are constructed of 4x4 char blocks. Max. 256 blocks can be used.

8.3 Map

Maximum theoretical map size is 255x128 blocks. However, that would take half
of C64's memory and can not thus be allowed really :)

8.4 Char-info

Each char has an additional byte that describes how the char behaves in regard
to actors (background collision detection). The bits are (note that some have
multiple meanings):

  1st bit - CI_GROUND
  Defines ground that the actors can walk on.

  2nd bit - CI_OBSTACLE
  Defines a horizontal obstacle like a wall. Ceiling collisions are also
  detected using this bit.

  3rd bit - CI_CLIMB
  Defines a ladder.

  4th bit - CI_DOOR
  Defines a door. There exist two kinds of doors: those facing in the Z-
  direction (away from screen) that need to be entered voluntarily (fire+up)
  and so called "side doors" that are entered automatically. The way how these
  are defined differs a bit. To define a Z-door, set the door bit on the chars
  1 char above the ground. To define a side door, set the door bit *on the
  ground*. The MW4 preview contains examples of both.

  5th bit - CI_STAIRS
  Use this in all diagonal stair junctions and for 2 chars in the beginning &
  end of stairs, to ensure the pathfinding AI can use them correctly. However,
  if you set them on every char that has CI_GROUND set, you will experience some
  slowdown :)

  5th bit - CI_SHELF
  Use this *without* CI_GROUND to denote shelves that items can sit on, but
  player or NPCs can not. Grenades will also bounce from these.

  6th bit - CI_LEFTLADDER
  Use to define a ladder where the actor faces left while climbing.

  6th,7th,8th bits - CI_SLOPE1,2,3
  Use these in conjunction with CI_GROUND to define smooth slopes in the
  terrain. The 8 slope patterns are:

  000,001  010      011      100      101      110      111
  ********        * *                       ** **
  ********       ** **                    **** ****
  ********      *** ***                 ****** ******
  ********     **** ****              ******** ********
  ********    ***** *****          ** ******** ******** **
  ********   ****** ******       **** ******** ******** ****
  ********  ******* *******    ****** ******** ******** ******
  ******** ******** ******** ******** ******** ******** ********

8.5 Char-colors

Each char can have its own color (full color-RAM scrolling).

8.6 Actor definitions

In AOMEDIT, you can set
- Actor's X,Y position at char accuracy
- Actor's type
- Actor's hitpoints (0 for default)
- Actor's initial AI mode (not all modes are available)
- Actor's group association
- Actor's weapon
- Actor's ID

There can be max. 128 actors within a level.

8.7 Door definitions

There can be max. 64 doors within a level. A door must be positioned one block
above the ground to work (see the MW4 preview level). For each door, a
destination door should be defined. For movement between levels, you have to
use a CovertScript trigger function to load the new level.

By using imagination, other usable level objects like switches or computers
can be defined by using doors and trigger functions.

8.8 Zone definitions

Zones are areas within a level that have certain scrolling limits, certain
background colors and certain music. The player actor can move between zones
only via doors.

For example, the inside & outside areas in the MW4 preview are different zones.
You can also use zones to generate exclusively horizontally- or vertically-
scrolling areas, as seen in many NES games :)

When the player actor is inside a certain zone, actors from other zones will
never "leak" onto the current zone, even that they are close. For example, a
"boss" character can have his own zone and you can be sure the boss will not
activate before the player actually is there.

There can be max. 16 zones in a level.


9. Music and sound effects
--------------------------

9.1 Music
---------

A music module is loaded into memory at $c000-$c7ff, so it can be max. 2KB.
Subtune 0 in each module is always the silence tune. The music modules are
created with GoatTracker 1.3x by the Pack-Relocate operation:

- Select playroutine 2 (Game, no playroutine saved with musicdata)
- Relocate to $c000
- Save as a raw binary (.BIN) file
- Exit GoatTracker, pack the .BIN file with CPACK (as done in the makefile)
  for including on the disk image

For the playtune() call,
tunes 0-7 are subtunes 0-7 from musicfile 0 (M0)
tunes 8-15 are subtunes 0-7 from musicfile 1 (M1)
tunes 16-23 are subtunes 0-7 from musicfile 2 (M2) and so on.

9.2 Sound effects
-----------------

Sound effects used by the CovertEngine are GoatTracker instruments that are
converted into sound effect format (actually, CovertScript data statements)
with the INS2SND utility. After this, the sound effects are joined together
in a chunk-datafile. See MW4SOUND.CS and the makefile for an example.

Sound effect priority is based on the order of sound effects in the memory
(same order as they appear in the chunk-datafile): the effects towards the
bottom of memory have higher priority, and can't be interrupted by lower
priority sounds.

When music is on, sound effects will be played only on channel 3. When music
is off, all channels are used in a rotating fashion.


10. Files on the game disk
--------------------------

The filenames on the disk are based on a letter indicating "category" and a
hexadecimal digit indicating file number within category. Actually, it is not
strictly a hexadecimal digit because the file number can go past F, all the
way to Z, and even to the special characters if needed :)

All the files are to be packed with CPACK utility unless mentioned otherwise.

The categories:

M - Music. Numbering starts from 0. Created with GoatTracker V1.3x by using
    playroutine 2, relocating at $c000, and and saving to .BIN (raw binary)
    format.

P - Pages. Covertscript bytecode pages. Numbering starts from 0.

D - Definitions. The item/weapon/bullet/special damage definition files.
    Numbering starts from 0. The preview has only one of them.

C - Chunk-files. Numbering starts from 0. These include the sound, actor, frame
    definitions, as well as sprites.

L - Levels. Numbering starts from 0. A level-file consists of multiple
    individually packed files concatenated. Here is how: (see the MAKEFILE how
    this is exactly done with the command-line utils)

    * First the level .MAP file (a chunk-datafile) is packed
    * Next, the level .BLK file (a chunk-datafile) is packed, and concatenated
    * Next, the level .CHR file is packed, and concatenated
    * Next, the level .CHI and .CHC files are concatenated into a temp file,
      packed, and concatenated into the main file
    * Finally, the level .LVA, .LVZ and .LVD files are concatenated into a temp
      file, packed, and concatenated into the main file.

G - Savegames. Generated by the game. Not packed.


11. Engine ASM function reference
---------------------------------

These are straight from the source code, with some comments added. Any raster
interrupt code is not included, because it is not meant to be directly called
in any case, and is not meant to be modified unless your really know what you are
doing :)

11.1 ACTOR.S
------------

11.1.1 INITACTORS
-----------------

Clears all actors onscreen.

Parameters: -
Returns: -
Modifies: A,X,Y,temp1-temp7

11.1.2 MOVEACTORS
-----------------

Moves actors.

Parameters: -
Returns: -
Modifies: A,X,Y,temp1-temp7

Comment: "moves actors" means that it calls the movement & AI routines of
every actor. Is called from the game main loop each game frame.

11.1.3 DRAWACTORS
-----------------

Draws actors and unpacks sprites.

Parameters: -
Returns: -
Modifies: A,X,Y,temp1-temp7

Comment: Is called from the game main loop each game frame.

11.1.4 DEPACKSPR
----------------

Subroutine that depacks one sprite.

Parameters: alo,ahi:Sprite address
            X:Sprite number
Returns: -
Modifies: A,Y

Comment: Is called by DRAWACTORS.

11.1.5 CALCSPRDELTAS
--------------------

Calculates sprite deltavalues for interpolation. To be called after the 4th
interpolated frame. Also plays queued sound effects.

Parameters: -
Returns: -
Modifies: A,X,Y, temp registers

Comment: DRAWACTORS jumps to this at its very end.

11.1.6 MOVEACTORX, MOVEACTORXDIRECT, SPAWNXMOD
----------------------------------------------

Does X-movement of an actor. MOVEACTORXDIRECT should be used with care
because it assumes that the flags reflect correctly the A register.

Parameters: X: Actor number, A: Amount of move (only in MOVEACTORXDIRECT)
            or Y: Actor number in SPAWNXMOD
Returns: -
Modifies: A, temp1 (only SPAWNYMOD)

Comment: SPAWNXMOD is meant for movement of "spawned" actors during the
spawning process (during this, the spawned actor index is in Y register while
while X is the origin actor index).

11.1.7 MOVEACTORY, MOVEACTORYDIRECT, SPAWNYMOD
----------------------------------------------

Does Y-movement of an actor. MOVEACTORYDIRECT should be used with care
because it assumes that the flags reflect correctly the A register.

Parameters: X: Actor number, A: Amount of move (only in MOVEACTORYDIRECT)
            or Y: Actor number in SPAWNYMOD
Returns: -
Modifies: A, temp1 (only SPAWNYMOD)

11.1.8 ACCACTORX
----------------

Does X-acceleration of an actor. Note: acceleration and speed limit must
always be same sign!

Parameters: X: Actor number, A: acceleration, Y: Speed limit
Returns: -
Modifies: A,Y,temp6

11.1.9 ACCACTORY
----------------

Does Y-acceleration of an actor. Note: acceleration and speed limit must
always be same sign!

Parameters: X: Actor number, A: acceleration, Y: Speed limit
Returns: -
Modifies: A,Y,temp6

11.1.10 BRAKEACTORX
-------------------

Brakes X-speed of an actor towards zero.

Parameters: X: Actor number, A: deceleration (always positive)
Returns: -
Modifies: A,temp6

11.1.11 BRAKEACTORY
-------------------

Brakes Y-speed of an actor towards zero.

Parameters: X: Actor number, A: deceleration (always positive)
Returns: -
Modifies: A,temp6

11.1.12 REVERSEACTOR, REVERSEXSPEED
-----------------------------------

Reverses actor direction / X-speed.

Parameters: X: Actor number
Returns: A: New direction / speed
Modifies: A

11.1.13 CHECKCOLLISION
----------------------

Checks if two actors have collided. They must both exist!

Parameters: X: Actor number
            Y: Actor number
Returns: C=1 actors collided
Modifies: A,temp1-temp5

Comment: "exist" means that actor type ("actt") must be nonzero.

11.1.14 CHECKHEADBUMP
---------------------

Checks if actor's head has hit the ceiling

Parameters: X: Actor number
Returns: -
Modifies: A,Y

Comment: This assumes the character's head is 4 chars above the ground (the
-4 char offset).

11.1.15 CHECKSIDEOBST, CHECKJUMPOBST
------------------------------------

Performs X-move of actor but if an obstacle blocks the way, does no
movement. CHECKSIDEOBST checks one char higher.

Parameters: X:Actor number
Returns: C=0 no obstacle, C=1 obstacle
Modifies: A,Y,temp1,temp2,temp3,temp4

Comment: Important function for actor move routines :)

11.1.16 TURNTOUP/DOWNSTAIRS
---------------------------

Turns a character to the direction of either up or down leading stairs,
but only if that is the target's direction! (for AI)
Does the checking only in junctions of stairs to preserve rastertime.

Parameters: X:Actor number
Returns: actd possibly changed
Modifies: A,Y,temp1,temp3

Comment: Used by pathfinding AI.

11.1.17 CHECKSTAIRS, CHECKSTAIRS_PREFERUP
-----------------------------------------

Checks if there is ground at actor's position or above/below. Will move
player one/two char(s) up or down, if necessary.

Parameters: X:Actor number
Returns: C=0 no ground, C=1 there is ground
         temp3 = result of GETCHARINFO
Modifies: A,Y,temp3

Comment: Another important function for actor move routines. Handles also
the smooth movement up/down slopes. CHECKSTAIRS_PREFERUP is used when the
actor is holding joystick up to climb up stairs.

11.1.18 CHECKLANDING
--------------------

Checks if a groundbased actor who jumps, has landed.
Note: to ensure correct operation do things in this order on one update:
- Accelerate actor if needed
- Move actor
- Check landing

Parameters: -
Returns: C=0 no landing, C=1 landed
Modifies: A,Y,temp2-temp3

Comment: yet another important function for actor move routines :)

11.1.19 GETFREELEVELINDEX
-------------------------

Searches for a free index in the leveldata table.

Parameters: -
Returns: C=1 Found (Y:Index) C=0 Not found
Modifies: A,Y

Comment: for REMOVEACTOR

11.1.20 GETFREEACTOR
--------------------

Searches for a free actor in the actor table.
When a free actor is found, some things are resetted here
(like actor bits)

Parameters: A:Last actor to be checked
            Y:First actor to be checked
Returns: C=1 Found (Y:Index) C=0 Not found
Modifies: A,X,Y

Comment: for spawning actors / creating new actors.

11.1.21 CREATEACTOR, INITBASICACTOR, INITCOMPLEXACTOR
-----------------------------------------------------

CREATEACTOR sets actor type & ID and goes to INITBASICACTOR.
INITBASICACTOR resets some values common to all actors.
INITCOMPLEXACTOR resets the actor's AI and initializes hitpoints + armor.
Note: actor pos & type must have been set for INITCOMPLEXACTOR.

Parameters: Y:Actor number
          A:Actor type (CREATEACTOR)
          X:Actor ID (CREATEACTOR)
Returns: -
Modifies: A,temp1,temp2,actptr

11.1.22 GETACTPTR, GAP_DIRECT
-----------------------------

Gets actor structure pointer.

Parameters: X:Actor number
            A:Actor type (only GAP_DIRECT)
Returns: -
Modifies: A,Y,alo-ahi

11.1.23 GETACTORBYTE, SETACTORBYTE
----------------------------------

Get/set actor definition structure bytes

Parameters: A:Actor type
            X:Byte index
            Y:Byte (SETACTORBYTE)
Returns: A:Byte (GETACTORBYTE)
Modifies: A,X,Y

Comment: This is used in the MW4 preview to change the enemies' properties
based on difficulty level, and to enable the ingame hitpoints cheat.

11.1.24 PROCESSHEALTH
---------------------

Process time-based health add/subtract for actors. Also increases game clock.

Parameters: -
Returns: -
Modifies: A,X,Y

Comment: Called from the game main loop.

11.1.25 SPAWNACTOR
------------------

Creates an actor with the same location & direction as the host actor.

Parameters: A:Actor type to be spawned
            X:Host actor
            Y:Free actor number
Returns: -
Modifies: A

Comment: GETFREEACTOR must have been called before.

11.1.26 REMOVEACTOR, REMOVELEVELACTOR
-------------------------------------

Removes current actor "properly"
REMOVELEVELACTOR puts actor back to leveldata.

Parameters: X:Actor number
Returns: -
Modifies: A,Y,temp1-temp2

11.1.27 REMOVEALLACTORS
-----------------------

Removes all actors (except player), returning them to leveldata.

Parameters: -
Returns: -
Modifies: A,X,Y

11.1.28 FOLLOWACTOR
-------------------

Copies coordinates of actor to another.

Parameters: X:Current actor
            Y:Actor to be followed
Returns: -
Modifies: A,Y,temp1

Comment: This is used by the speech-balloons to follow the actor who is
speaking.

11.2 AI.S
---------

11.2.1 THINKER_MAMMAL
---------------------

Main AI routine for NPCs

Parameters: X:Actor number
Returns: -
Modifies: A,Y

11.2.2 GETTARGETDISTANCE
------------------------

Calculates signed & absolute distances of actors

Parameters: X:Actor number, Y:Target actor
Returns: -
Modifies: A,Y

Comment: The distances are put to targetxdist, targetabsxdist, targetydist,
targetabsydist (on zeropage)

11.2.3 ENEMYSCORE
-----------------

Scoring for defeating the enemy

Parameters: X:Actor number
Returns: -
Modifies: A,Y,temp1

Comment: "scoring" is a bit misleading, as MW4 preview does not calculate score
as of now. Instead this routine increments the corresponding takedown counter
(lethal, nonlethal, nonorganic) if player was responsible for the takedown.
Enemies dropping their weapon and calling the T_TAKEDOWN trigger is also
handled by this routine.

11.2.4 SAYNOPTR,SAYIDLENOPTR
----------------------------

Routine for an actor saying things. Called from the VM.
SAYIDLE will also fail if actor in combat.

Parameters: ptr:24bit text pointer
Returns: C=1 successful C=0 not successful
Modifies: A,X,Y,temp1-3

Comment: The "NOPTR" in the function name means that A,X,Y variables (the
pointer parameter) have been already loaded by say() and sayidle() CovertScript
functions, and serves also to distinguish from these functions.
This function and the following functions require that the VM thread is
"focused" on the actor we are operating with.

11.2.5 GOINTOALERT
------------------

Instructs an actor to go into alert mode. If already alerted or in combat,
does nothing. Called from the VM.

Parameters: A:Target actor ID ($0-$7f)
Returns: C=1 success C=0 failure
Modifies: A,X,Y,temp1-temp3

11.2.6 GOTOTARGET
-----------------

Routine that instructs an actor to go to a waypoint or follow another actor.
Will not do that if in combat. Called from the VM.

Parameters: A:Target actor ID ($0-$7f) or waypoint ($80-$8f)
Returns: C=1 success C=0 failure
Modifies: A,X,Y,temp1-temp3

11.2.7 CHECKDISTANCE
--------------------

Routine that checks distance to another actor. Called from VM.

Parameters: A:Target ID
Returns: X,Y:Absolute distances if C=1
Modifies: A,X,Y,temp1-temp3

11.2.8 CHECKWAYPOINT
--------------------

Routine that checks if actor has reached a waypoint. Called from VM.

Parameters: A:Waypoint ($80-$8f)
Returns: C=1 reached C=0 not reached
Modifies: A,X,Y,temp1-temp3

Comment: this is last of the "focused" actor functions. Not all of these
functions are defined in MW4EXT.CS because they were not needed in the preview.

11.2.9 MAKENOISE
----------------

Alerts NPCs to noise made by current actor.

Parameters: A:Noise level (1-3)
            X:Actor number (position is important)
Returns: -
Modifies: A,Y

11.3 CONTROL.S
-------------

11.3.1 GETCONTROLS
------------------

Reads joystick + scans the keyboard.

Parameters: -
Returns: -
Modifies: A,X

Comment: Joystick & keyboard control info are returned in the variables
"joystick", "keypress" and "keytype". In addition, the previous joystick
control is in the variable "prevjoy".

11.3.2 SCANKEYS
---------------

Reads keyboard.

Parameters: -
Returns: -
Modifies: A,X,Y

Comment: Called by GETCONTROLS.

11.3.3 KEYCONTROL
-----------------

"Joystick" control with keyboard, with keys Q W E and SHIFT for fire.
                                            A   D
                                            Z X C

Parameters: -
Returns: -
Modifies: A,X,Y

Comment: Called by GETCONTROLS.

11.3.4 GETFIRECLICK
-------------------

Checks if fire button has been pressed shortly.

Parameters: -
Returns: C=0 not pressed, C=1 pressed
Modifies: A

11.4 FILE.S
----------

11.4.1 RETRYPROMPT
------------------

Retry prompt for loading.

Parameters: -
Returns: -
Modifies: A,X,Y

Comment: Displays the "load error" text and waits until firebutton pressed.

11.4.2 MAKEFILENAME
-------------------

Creates the filename.

Parameters: A:File number X:File type letter (file category)
Returns: filename
Modifies: A

Comment: Used in preparation to OPENFILE etc.

11.4.3 SAVEFILE
---------------

Saves a file.

Parameters: filename, (alo,ahi):startaddress, (tempadrlo,tempadrhi):endaddress
Returns: -
Modifies: A,X,Y

Comment: Saving can be a lengthy process because the fastloader drive code
needs to be loaded and re-initted after saving.

11.4.4 LOADFILERETRY
--------------------

Loads a file with retry.

Parameters: filename, A,X:startaddress
Returns: A=0 OK, A=nonzero -> error
Modifies: A,X,Y

Comment: Loads a *packed* file.

11.4.5 LOADCHUNK
----------------

Retries loading of a chunkfile, until successful

Parameters: Y:Chunk number

Returns: -
Modifies: A,X,Y,temp regs

11.4.6 LOADSPRITES
------------------

Loads a sprite-chunk. does not load if it is already in memory!

Parameters: Y:Chunk number

Returns: -
Modifies: A,X,Y,temp regs

11.4.7 CLOSEFILE
----------------

"Drains" (closes) a file.

Parameters: -
Returns: C=1, A:Errorcode or 0 on EOF
Modifies: A

Comment: Reads until EOF, this is necessary at least with the fastloader.

11.4.8 LOADALLOCCHUNK
---------------------

Allocates & loads a chunkfile.

Parameters: Filename
            Y:Chunk number
Returns: C=0 OK C=1 Error
Modifies: A,X,Y,temp regs (chunk number stored to temp1)

Comment: Used if "filename mapped directly to chunk number" is not desired.

11.4.9 PURGECHUNK
-----------------

Removes a chunk from memory.

Parameters: Y: Chunk number
Returns: -
Modifies: A,X,temp regs

11.4.10 GETOBJECTADR
--------------------

Gets object address

Parameters: A:Object number within chunk (0-127)
            Y:Chunk number
Returns: alo,ahi:Object address
Modifies: A,Y,tempadr

11.5 MENU.S
-----------

11.5.1 MENU
-----------

Handles activation of the ingame menu by pressing firebutton only for a
sufficient time. Actual menu code is done in the script.

Parameters: -
Returns: -
Modifies: A,Y

Comment: Called from the game main loop.

11.5.2 EXITPROGRAM
------------------

Resets the C64.

Parameters: -
Returns: -
Modifies: lots of variables :)

11.5.3 LOADGAME, SAVEGAME
-------------------------

Loads/saves game. LOADGAME never returns because VM state information is
replaced.

Parameters: A:Game number
Returns: -
Modifies: A,X,Y

11.5.4 DRAWARROWS
-----------------

Draws the menu/conversation choice selection arrows.

Parameters: A:Current choice
            X:Maximum number of choices-1
Returns: -
Modifies: A,X,Y

11.6 INIT.S
-----------

11.6.1 BUFFERTOREU
------------------

Buffers a file into REU memory.

Parameters: Filename
Returns: C=0 successful
         C=1 error (A holds errorcode, $00 means out of REU memory)

Modifies: A,X,Y

Comment: Loading chunk files will overwrite this routine, as it belongs
to the initialization routines.

11.7 ITEM.S
-----------

11.7.1 INITINVENTORY
--------------------

Empties player inventory and adds fists.

Parameters: -
Returns: -
Modifies: A,Y

Comment: Adding fists was moved to CovertScript code :)

11.7.2 FINDITEM
---------------

Tries to find an item of certain type from the player's inventory

Parameters: A:Item type
Returns: C=1 item found (Y:Inventory index), C=0 not found
Modifies: Y

11.7.3 SORTINVENTORY
--------------------

Sorts items to ascending order. Uses horrible bubblesort :-)

Parameters: -
Returns: -
Modifies: A

Comment: Called by functions that modify the inventory.

11.7.4 ADDAMMO
--------------

Adds ammo to item

Parameters: A:Amount to add
            Y:Inventory index
Returns: A:Amount that was really added
Modifies: A,Y,temp1-temp3

Comment: In the source code, the "item count" of all items is called "ammo" :)

11.7.5 REMOVEITEM
-----------------

Removes an item from inventory

Parameters: A:Item number
Returns: C=1 success, C=0 failure (item did not exist)
Modifies: A,Y,temp1

11.7.6 DECREASEAMMO
-------------------

Decreases ammo of item

Parameters: A:Amount of decrease
            Y:Inventory index
Returns: -
Modifies: A,Y (if item must be removed),temp1

11.7.7 CHECKPICKUP
------------------

Checks for player picking up items

Parameters: X:Player actor number
Returns: -
Modifies: A,Y,temp1-temp7

Comment: Called by the "human" actor move routine for actor index 0 (player).

11.7.8 ADDITEM
--------------

Adds an item to player inventory

Parameters: A: Amount
            X: Item type
Returns: C=1 Add successful, C=0 inventory full or max.amount carried
Modifies: A,Y,temp1-temp2

Comment: Called by CHECKPICKUP and also by CovertScript code.

11.7.9 UPDATEPANEL, TOTALUPDATEPANEL
------------------------------------

Draws changes in the score panel.

Parameters: -
Returns: -
Modifies: A,X,Y,temp1-7, other temp regs

Comment: Called from the game main loop. TOTALUPDATEPANEL will force the update
of the panel (normally only changes are updated).

11.7.10 DRAWHEALTHBAR
---------------------

Draws a health bar to the text panel.

Parameters: A:Length
            X:End offset in the text panel
            Y:Start offset in the text panel
Returns: -
Modifies: A,X,Y

Comment: Called by UPDATEPANEL.

11.7.11 CONVERT8BITS, CONVERT16BITS
-----------------------------------

Converts a binary number to BCD.

Parameters: A,X: binary number
Returns: temp4-temp7: BCD number
Modifies: A,X

11.7.12 PRINTBCDDIGIT, PRINTBCDDIGITS
-------------------------------------

Prints BCD numbers to the text panel.

Parameters: X:Offset in the text panel
            Y:offset to BCD digits, relative to temp4
Returns: X autoincremented
Modifies: A,X

11.7.13 SETMSGPTRS
------------------

Sets the address where to get script messages

Parameters: Ptr:24bit pointer to the start of message pointers in script data
Returns: -
Modifies: A

11.7.14 GETITEMNAME, GETMSGPTR
------------------------------

Parameters: A:Message/item number
Returns: Data PC:24bit pointer to message/itemname
Modifies: A,X,Y

11.7.15 PRINTMSG, PRINTMSGPTR, PRINTMSGCONT
-------------------------------------------

Prints a message from the script data to the text window.

Parameters: A:message number (PRINTMESSAGE) or
            Ptr:24bit message ptr (PRINTMESSAGEPTR)
Returns: A=1 if text did not fit on one screen
Modifies: A,X,Y,temp regs

11.7.16 PTW_CLEARRESTOFROW
--------------------------

Clears the remainder of the current message window row.

Parameters: -
Returns: -
Modifies: A,X,Y

11.7.17 PTW_OUTPUTCHAR
----------------------

Outputs a character on the current message window row.

Parameters: A:Character to output
Returns: -
Modifies: A,X,Y

11.7.18 PRINTFMTTEXT
--------------------

Prints formatted text to the text window. Called from the VM.

Parameters: ptr:24 bit text address
Returns: -
Modifies: A,X,Y

Comment: Look at MW4TITLE.CS to see how the text is "formatted". :)

11.7.19 RESETMSG
----------------

Resets the message window.

Parameters: -
Returns: -
Modifies: A,X,Y

Comment: Clears the message window and stops further message screens (long
message) from appearing.

11.7.20 CLEARTEXTWINDOW
-----------------------

Clears the text window.

Parameters: -
Returns: -
Modifies: A,X

11.8 KRNDPACK.S
---------------

11.8.1 LOADFILE
---------------

Opens & loads a packed file.

Parameters: filename
            X,Y: starting address in memory
Returns: C=0 loading successful, C=1 error (error code in A)

11.8.2 GETPACKEDBYTE
--------------------

Get byte from packed stream.

Parameters: -
Returns: C=0 A,X:Byte, flags reflect it correctly
         C=1 A:zero EOF, stream ended successfully
         C=1 A:nonzero Error of some kind, call GETBYTE again to know more

Modifies: A,X

11.9 KRNLOAD.S
--------------

11.9.1 GETBYTE
--------------

Gets a byte from an opened file.

Parameters: -
Returns: C=0 OK, A contains byte
         C=1 File stream ended. A contains the error code:
             $00 - OK, end of file
             $01 - Sector read error (only with fastloading)
             $02 - File not found
Modifies: A

Comment: During the time a file is open without using fastloader, KERNAL will
be switched on. So be careful :)

11.9.2 OPENFILE
---------------

Opens a file either with slow or fast loader, or from REU if it has been
buffered. If a file is already open, does nothing!

Parameters: filename
Returns: -
Modifies: A,X,Y

11.10 LEVEL.S
-------------

11.10.1 LOADLEVEL
-----------------

Loads a level.

Parameters: A:Level number
            X:0 Load also leveldata
            X:1 do not load leveldata (on Load Game option)
Returns: -
Modifies: A,X,Y,temp1-temp7

11.10.2 INITMAP
---------------

Calculates start addresses for each map-row and for each block. This is
necessary after loading and after purging chunks.

Parameters: mapsizex
Returns: -
Modifies: A,X,Y

Comment: All the current file-handling routines in the engine call this, so
you do not have to worry of it.

11.10.3 ADDACTORS
-----------------

Adds actors from the leveldata to the game.

Parameters: -
Returns: -
Modifies: A,X,Y,temp1-temp7

Comment: Called from game main loop.

11.10.4 ADDACTOR
----------------

Adds an actor with a certain ID immediately. does not call its appear script.
Usually called from the VM to make some modifications to actor properties
(like the jump of ninjas when they appear through the windows in the preview)

Parameters: A:Actor ID
Returns: C=1 if ID found and actor added successfully
Modifies: A,X,Y,temp1-temp7

11.10.5 UNHIDEACTORS
--------------------

Un-hides all hidden actors (leveldata Y-coord >= $80) and sets them to PATROL
mode if they are IDLE or SPARRING. Doing this in CovertScript was too slow,
there was a definite pause when the Ninjas appeared :)

Parameters: -
Returns: -
Modifies: A,X

11.11 MATH.S
------------

11.11.1 RANDOM
--------------

Returns a 8bit pseudorandom number.

Parameters: -
Returns: A:number ($00-$ff)
Modifies: A

11.11.2 MULU
------------

Unsigned multiplication

Parameters: A:first value to be multiplied
            Y:second value to be multiplied
            X:zeropage base
Returns:    zeropage:Result
            A:highbyte of result
Modifies:   A,X,Y

Comment: You do not need this to do multiplies in CovertScript code! Simply use
the multiply operator as in C.

11.11.3 DIVU
------------

Unsigned divide

Parameters: A:value to be divided
            Y:divider
            X:zeropage base
Returns:    zeropage:Result
            A:remainder
Modifies:   A,X,Y

Comment: You do not need this to do divides or modulos in CovertScript code!
Simply use the divide or modulo operator as in C.

11.11.4 ASR
-----------

Arithmetic shift right.

Parameters: A:number. Flags must reflect its value!
            Y:bits to shift
Returns: A:number
Modifies: A,Y

Comment: This might be useful in CovertScript, because its shift operators are
unsigned.

11.11.5 NEGATE
--------------

2's complement negation.

Parameters: A:number.
Returns: A:number negated
Modifies: A

Comment: You do not need this for negates in CovertScript code! Use the C-like
operator instead.

11.12 PLAYER.S
--------------

11.12.1 THINKER_PLAYER
----------------------

Interactive character (joystick control).

Parameters: X:Actor number
Returns: -
Modifies: A,Y

Comment: If the variable "convmode" (conversation/cutscene mode) is nonzero,
will jump to THINKER_MAMMAL (switching player actor under AI control)

11.12.2 MOVE_HUMAN
------------------

General human move routine

Parameters: X:Actor number
Returns: -
Modifies: A,Y

Comment: Studying this will tell you everything you need to know about
CovertEngine actor move routines :)

11.12.3 MOVE_ZSIGN
------------------

'Z' sign move routine

Parameters: X:Actor number
Returns: -
Modifies: A,Y

Comment: A nice example of a "simple" actor move routine, the "Z"-signs
float upwards and perform a wave-like motion. They also disappear after a
certain time.

11.12.4 MOVE_BALLOON
--------------------

Balloon (actors' speaking) move routine

Parameters: X:Actor number
Returns: -
Modifies: A,Y

11.12.5 SPAWNBALLOON
--------------------

Spawns a balloon for actor's speaking. Overwrites always the 3rd particle
effect actor!

Parameters: Y:Actor number
Returns: -
Modifies: A,Y,temp1,actptr

11.12.6 CHECKTRIGGERS
---------------------

Checks player's positional triggers & "near NPC" triggers.

Parameters: -
Returns: -
Modifies: A,X,Y

Comment: Called from the game main loop.

11.12.7 CHECKDOORS
------------------

Checks for entering doors.

Parameters: X:Actor number 0 (player)
Returns: -
Modifies: A,Y,temp registers

Comment: Called from the "human" move routine, when dealing with the player
actor.

11.12.8 CHECKNPCS
-----------------

Checks for talking with NPCs.

Parameters: X:Actor number 0 (player)
Returns: -
Modifies: A,Y,temp registers

Comment: Called from the "human" move routine, when dealing with the player
actor.

11.12.9 TRANSPORTPLAYER, CENTERPLAYER
-------------------------------------

Transports player to door's destination. Called from VM. CENTERPLAYER does not
move the player actor, but centers it and instructs screen to be redrawn.
CENTERPLAYER is also responsible for detecting the current zone the player is
within.

Parameters: -
Returns: -
Modifies: A,X,Y

11.13 SCREEN.S
--------------

11.13.1 CLEARTEXTSCREEN
-----------------------

Clears/shows the textscreen

Parameters: -
Returns: -
Modifies: A,X,Y

11.13.2 UPDATEBLOCK
-------------------

Updates a block on the map. The actual work of putting it on the screen will
happen in the raster interrupt.

Parameters: A:New block
            X,Y:Map position
Modifies: A,X,Y,temp1-2

Comment: There is a queue of 4 onscreen block updates max. If you fill the
queue, the rest of the screen updates will be discarded. However, the blocks
will always be updated on the level map! The preview uses this routine when
the Ninjas break through windows and the secret passage is revealed.

11.13.3 GETCHARPOSINFO
----------------------

Gets charinfo from actor's position

Parameters: X:Actor number
Returns: A:charinfo
Modifies: Y,tempadr

Comment: This is thes simplest of background collision check functions, used
for example with the bullet movement.

11.13.4 GETCHARPOSINFOOFFSET
----------------------------

Gets charinfo from actor's position, with a certain Y offset

Parameters: X:Actor number, A:Y offset in chars (positive or negative)
Returns: A:charinfo
Modifies: Y,tempadr

11.13.5 GETCHARPOSINFOXY
------------------------

Gets charinfo from actor's position, with both X & Y offset

Parameters: X:Actor number, A:Y offset in chars (positive or negative)
            temp1:X offset in chars (positive or negative)
Returns: A:charinfo
Modifies: Y,tempadr

Comment: Notice the variations GETCHARPOSINFOXY2 & 3. These pass the parameters
differently.

11.14 SOUND.S
-------------

11.14.1 PLAYSFX
---------------

Plays (queues) a sound effect.

Parameters: A:Sound effect number
Returns: -
Modifies: A,X,Y

Comment: Queued sound effects will be played at the end of a game frame, to
guarantee sound synchronization.

11.14.2 PLAYGAMETUNE
--------------------

Plays an "ingame" tune. This means it will not be played if music has been
turned off.

Parameters: A:Song number
Returns: -
Modifies: A

11.14.3 TOGGLEMUSIC
-------------------

Toggles music. Takes care of restarting the last played song if necessary.

Parameters: -
Returns: -
Modifies: A

Comment: Before calling this, musicmode ^= 1; or lda musicmode; eor #$01;
sta musicmode has to be done manually, so the name of the function is a bit
misleading :)

11.14.4 PLAYTUNE
----------------

Plays a tune regardless of whether music is active.

Parameters: A:Song number
Returns: -
Modifies: A,X,Y

11.15 VM.S
----------

11.15.1 VM_PTRTODATAPC
----------------------

Transfers the thread's A,X,Y variables into the DATA PC.

Parameters: -
Returns: -
Modifies: A

Comment: Only one DATA PC exists for all the threads, therefore for example
a long message is interrupted if also formatted text is printed meanwhile.
This is called by the message & formatted text functions, you do not have to
care about it much :)

11.15.2 VM_GETSCRIPTDATABYTE
----------------------------

Reads a byte from the DATA PC, autoincrementing it. Note that there is only
one DATA PC for all threads, it's used for all text printing among other
things.

Parameters: -
Returns: A:Byte
Modifies: A,X

11.15.3 VM_GETSCRIPTBYTE
------------------------

Reads a byte from the thread's PC, autoincrementing it.

Parameters: -
Returns: A:Byte
Modifies: A,X

Comment: do not call this from CovertScript, it would seriously mess up the VM
instruction decoding :)

11.15.4 RUNNEXTVM
-----------------

Runs instructions on all VMs until they perform a "release". Extremely
important rule: this routine (or RUNVM) may not be re-entered from an extern-
called function (VM runloop already executing)

Parameters: -
Returns: -
Modifies: A,X,Y

Comment: Called from the game main loop.

11.15.5 FOCUS
-------------

Sets thread to focus on an actor ID. The actual actor index can be read from
the variable "act"; it is $ff if actor is not present, which will cause indexed
writes to be skipped and indexed reads to return always 0.

Parameters: A:Actor ID
Returns: -
Modifies: A,X,Y

11.15.6 FINDACTORID
-------------------

Searches all 8 complex actors for the actor ID.

Parameters: A:Actor ID
Returns: Y:Actor index, or $ff if not found.
         C=1 if found
Modifies: Y

11.15.7 SETTRIGGER
------------------

Sets a new event trigger. Either searches for an empty slot in the trigger
table or replaces an existing trigger of the same type & ID.

Parameters: ptr:24bit pointer to trigger data (type,id,ptr)
Returns: C=1 success (Y=trigger index), C=0 out of triggers
Modifies: A,X,Y,temp1-2

11.15.8 CLEARTRIGGERS
---------------------

Clears all triggers, except T_GAME triggers. Usually done in preparation for
a new level. Also resets the "near" triggering mechanism.

Parameters: -
Returns: -
Modifies: A,Y

11.15.9 SPAWN
-------------

Spawns a new VM thread.

Parameters: ptr:24bit start address
Returns: C=1 success, C=0 no free VMs
Modifies: A,X,Y

11.15.10 SETBIT, CLEARBIT, CHECKBIT
-----------------------------------

Gets/sets/clear plot bits

Parameters: A:Bit number
Returns: A:Bit status (only CHECKBIT)
Modifies: A,X,Y

11.15.11 VM_GETFOCUS
--------------------

Gets the actor number that the VM is focused to and verifies it has the
correct ID. This is needed in almost every actor-related function to be
called from a script.

Parameters: vmnum:VM number
Returns: Z=1 correct ID, X:VM num, Y:actor num
Modifies: A,X,Y

11.15.12 TRIGGER
----------------

Starts a virtual machine if trigger found.
Because the PICKUP, APPEAR & TAKEDOWN scripts are executed immediately,
they might change zeropage temp variables, so do not rely on them in the
code that calls TRIGGER!

Parameters: X: Trigger type (T_GAME, T_PICKUP etc.)
            A: Trigger ID. If script has a trigger with ID $ff, it matches
               any ID
Returns: C=1 trigger found, VM started
Modifies: A,X,Y

11.15.13 GETFREEVM
------------------

Gets number of a free VM.

Parameters: -
Returns: C=1 free VM found, number in X
         C=0 no free VMs
Modifies: A,X

11.15.14 STOPALLVM
------------------

Stops execution of all other virtual machines.

Parameters: -
Returns: -
Modifies: A,X

11.16 WEAPON.S
--------------

11.16.1 LOADDEFS
----------------

Loads weapon/bullet/item/specialdamage definitions.

Parameters: A:Definition file number (usually 0)
Returns: -
Modifies: A,X,Y,temp regs

11.16.2 ATTACK
--------------

General attack routine for actors

Parameters: X:Actor number
            A:Direction (0=straight 1=up 2=down)
            actwpn:weapon number
Returns: C=1 attack successful
Modifies: A,Y,temp1-7

11.16.3 ATTACK_HUMAN
--------------------

Attack handling of a human actor

Parameters: X:Actor number
Returns: -
Modifies: A,Y,temp1-7

Comment: Includes reloading, melee animation etc.

11.16.4 CHECKJOYDOWN
--------------------

Checks if player has pressed FIRE+DOWN (use item & reload weapon)

Parameters:
Returns: Z=1 has pressed, Z=0 has not
Modifies: A,Y

11.16.5 MOVE_GRENADE
--------------------

Grenade & item movement

Parameters: X:Actor number
Returns: -
Modifies: A,Y

Comment: This move routine implements bouncing physics.

11.16.6 MOVE_SHURIKEN
---------------------

Shuriken movement

Parameters: X:Actor number
Returns: -
Modifies: A,Y

11.16.7 MOVE_MELEEHIT
---------------------

"Virtual" melee bullet. Very minimal "move-routine" :)

Parameters: X:Actor number
Returns: -
Modifies: A,Y

11.16.8 MOVE_BULLET
-------------------

Bullet movement with background collision detection

Parameters: X:Actor number
Returns: -
Modifies: A,Y

11.16.9 MOVE_SMOKECLOUD, MOVE_GORE
----------------------------------

Smokecloud & gore animation

Parameters: X:Actor number
Returns: -
Modifies: A,Y

11.16.10 WEAPONANIMATION
------------------------

General subroutine for one-sprite oneshot animation

Parameters: X:Actor number
            Y:Frame delay
            A:Number of frames to play
Returns: C=1 when animation finished, otherwise C=0
Modifies: A,temp1,temp2

11.16.11 AREAEFFECT
-------------------

Checks explosion radius for all NPCs, and punishes them as necessary.

Parameters: X:Actor number
            A:Radius of explosion in blocks
Returns: -
Modifies: A,Y,temp registers,acthp,actsx

11.16.12 CHECKBULLETCOLL
------------------------

Checks collision of bullet. To be called from the bullet's move routine.

Parameters: X:Actor number
Returns: C=0 no collision, C=1 collision
Modifies: A,Y,temp registers

11.16.13 PUNISH, PUNISH_NOARMOR
-------------------------------

Punishes actor (deals damage)

Parameters: A:Amount of damage
            X:Actor number.
Returns: -
Modifies: A,Y,temp3-temp4

Comment: PUNISH_NOARMOR bypasses the actor's armor, and reduces hitpoints
directly.


12. CovertEngine memory map
---------------------------

12.1 C64 memory map
-------------------

$0002-$007f Engine zeropage variables
$00fc-$00ff GoatTracker playroutine zeropage variables
$0100-$017f Sprite variables
$02a7-$02ff Sprite variables continued
$0334-$1xxx General variable area, begins with the CovertScript variable area
$1xxx-$6b7f Memory pool for allocation
$6b80-$6fff Loadbuffer, depackbuffer, maptbl and blocktbl
$7000-$bfff Main engine code
$c000-$c7ff Music data
$c800-$dfff CovertScript VM bytecode (3 2KB pages)
$e000-$ffff Depacked sprites, screens and charsets

As the engine code grows, maincodestart ($7000, defined in DEFINE.S) can be
located lower in the memory. This will result in a smaller memory pool.

12.2 Diskdrive memory map (fastloader)
--------------------------------------

$0300-$03ff Directory cache
$0400-$04ff Sector buffer
$0500-$067f Drive code
$0680-$07ff Directory cache


13. Conclusion
--------------

This document serves a dual purpose. Firstly, it is intended to make the engine
actually understandable and usable to outsiders :) but secondly, it also serves
as a document for me should I forget something of how the engine works during
the months that still await before MW4 will be finished.

Honestly, I do not expect anyone else to actually create another game with this
engine. Experience has proven that most C64 programmers (including me) like to
produce their own game engines from ground up. It is part of the C64 "magic",
because it is possible with moderate effort, unlike a PC 3D engine or something.

This engine is also quite general and quite heavy in its structure. Likely, it
is unnecessarily complicated for classic pure C64 action games. But I believe
it's very fitting for action/adventure games with certain "modern" influences
(for example, influences from storydriven PC 1st person games and such
:) ).

However, I would be glad to be proved wrong :)