    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 :)