                       +-----------------------------+
                       | Intro to Coding Unreal DLLs |
                       |    ---------------------    |
                       | Chris Prince (aka Vulcoris) |
                       |  cprince@u.washington.edu   |
                       |       October, 1998         |
                       +-----------------------------+

INTRODUCTION:
=============

This package contains some files and information that show how to write your
own simple DLLs in Unreal.  I've spent a fair amount of time figuring out how
to do what's explained here.  Please feel free to distribute this information
in any way you like.  However, if you find it useful, you might drop me an
e-mail saying so (that's the greatest reward for me).

Notes:

  - This stuff has only been tested with the v2.09beta patch, but I imagine it
      probably works with other versions too.
  - I am aware there are a few serious omissions in this document.  But I am
      releasing this information anyway in the hopes that someone else (who
      has more time) can benefit from this information and expand upon it.



FILES:
======
Here are the files that should be included in this package:

Filename                          Description
------------------------------    --------------------------------------------
CPP/unrMacro.h                    Some necessary macros and structs
CPP/unrClass.h                    *Very incomplete* Unreal class listing
                                    (a hack really, to get things to compile)

CPP/dlltest.dsw, CPP/dlltest.dsp  MSVC 6.0 Project Files
CPP/dllmain.cpp                   Our DLL-based Unreal class
CPP/dlltest.dll                   The compiled DLL file

USCRIPT/DLLTrigger.uc,
 USCRIPT/dlltest.u                The UnrealScript side of our DLL-based class

MAP/DLLmap.unr                    A test map that uses our DLL-based class

UCLASSES/*.h                      Unreal .h files, generated using
                                    "unreal -make -h" (after some tweaking to
                                    the exported class files).  Not used, but
                                    someone could probably find a use for them
                                    (they're a pain to generate yourself).

readme.txt                        What you're reading now (duh!)



INSTRUCTIONS:
=============

If you just want to try out this stuff, do the following:

  1.  Copy "CPP/dlltest.dll" and "USCRIPT/dlltest.u" to your Unreal/System
        directory.
  2.  Copy "MAP/DLLmap.unr" to your Unreal/Maps directory.
  3.  Open DLLmap.unr from inside Unreal, and walk toward the "brighter"
        corner (a DLL-based trigger lies near there).  You should see a
        message as soon as you've triggered it.
  4.  Exit Unreal, and notice that you now own a new file ("c:\unrtest.txt").
        Yes, that's right, we did it using plain old C++ code in a DLL!

If you want to know more about how this works, then read on, young Jedi!



HOW TO "ROLL YOUR OWN":
=======================

OK, let me give a quick explanation of the essential components in writing
your own Unreal DLL.  If there are any discrepancies between this and the
source code, believe the source code (as you always should :-).

First, I need to mention that your DLL name and your UnrealScript package
name must be the same.  So, for example, if your UnrealScript package is
named "mypackg.u", you need to make sure your DLL is called "mypackg.dll".

Also, you'll probably want to create your DLL and put it in the Unreal/System
directory *before* you write your UnrealScript code.  Otherwise, UnrealEd will
probably crash while compiling your UnrealScript code, because it won't be able
to find the corresponding things in your DLL (yes, it checks for them).


C++
---
Now, let's start looking at the C++ side of things:


  Header Files
  ------------
First, you'll want to #include the two header files I've given you
("UnrMacro.h" and "UnrClass.h") in your C++ source file.

UnrMacro contains a bunch of macros I've created that you'll need in order to
get your DLL to work.  Much of it is used for generating the DLL-export tokens
required to get Unreal to correctly "recognize" your DLL.  See below for an
explanation for exactly how to use these macros.

UnrClass just lists a few UnrealScript classes that my new class uses.  These
are just here so that things compile correctly.  It's a hack, really.  It
might be nice if someone out there could put together a more comprehensive
version of UnrClass.h, so that people don't have to do this every time
(hint, hint :-).  At least until Tim releases the "official" headers.


  IMPLEMENT_PACKAGE()
  -------------------
Next, you'll need to include an IMPLEMENT_PACKAGE statement (this is one of
those macros I was talking about above).  According to the UnrealScript
on-line documentation, you need to do this once per package.  The argument
must be the same as whatever your DLL will be called (which, you'll recall,
must match your UnrealScript package name).  So for example, if my DLL is
called "mypackg.dll", I'd want to use the following:

    IMPLEMENT_PACKAGE(mypackg);

See the source code if you want to know what's *really* going on here (that
goes for the stuff below, too).


  C++ Class and Function Names
  ----------------------------
Now, the meat of your code --- the classes and functions.  You'll want to
declare things pretty much just like in normal C++, but different. :-)  Here
are the most important things to notice:

    - Any UnrealScript class (say, "Foo") must be referred to in your C++ code
        as "AFoo" (i.e. put an "A" on the front).
    - Any UnrealScript function (say, "Bar") must be referred to in your C++
        code as "execBar" (i.e. put an "exec" on the front).

There are also a couple of macros you must use here:

    - After declaring your class, use the EXPORT_CLASS() macro with the
        C++ (and not UnrealScript) name of your class.  Example:
            EXPORT_CLASS(AFoo);
        Don't forget the "A" in front of "Foo"!
    - You'll also need to use the EXPORT_FUNC() macro to make each of your
        functions accessible.  This macro takes 2 parameters -- the class that
        the function is a member of, and the function name itself.  Example:
            EXPORT_FUNC(AFoo,execBar);
        Again, notice that we need the C++ names and not the UnrealScript
        names (so remember the "A" in "AFoo", and the "exec" in "execBar").


  Some Notes About Functions
  -------------------------- 
Since UnrealScript doesn't use a standard C-style calling convention (as far
as I can tell), it needs to use a special mechanism to transfer information
to/from C++ code.  As a result, you need to do a couple of "special" things
when writing your C++ functions.

      Function Prototype
      ------------------
The function prototype of your C++ functions (or at least the ones accessible
from UnrealScript) should *always* be as follows:

  void execBLAHBLAHBLAH( FFrame& Stack, BYTE*& Result )

So, what's going on here?  'Stack' is used to pass-in arguments --- it seems
you need to call a function to "fetch" each parameter in turn (if you don't
believe me, either look at http://unreal.epicgames.com/unrealvcdebug.bmp , or
you could examine the code in a debugger).  To return a value, you need to
write it back using the Result pointer.

      Arguments and Return Values
      ---------------------------
To be honest, I haven't played around with these too much (largely due to my
various time contraints :-( ), and I don't know *exactly* how to pass and
return values.  This is definitely the biggest "gap" in this document.
However, I have *some* ideas about how things need to be done, and I feel it's
very do-able.  If someone out there does mess around and get things to work,
I'd be happy to hear about it.  Anyway, here's some of what I *do* know:

        - After fetching all of the function arguments (assuming you figure
            out how -- or even if you don't :-), you will need to use a macro:
                PARAMS_FINISHED;
            This does some munging around in the 'Stack' argument that
            prevents your program from locking up. :-)

            (For you enterprising souls out that want to figure out how to
            access parameters, see my FFrame definition in the source code
            for some a little insight into how things work here.)

        - To return a value, I *think* you can just write to (*Result), but
            this might fail if the return value is larger than a pointer
            (4 bytes under Win32).  Or it might work fine -- I just haven't
            had a chance to try it yet.

  C++ Summary
  -----------
Check out the included source code in "dlltest.cpp".  That's a fairly good
summary for what you need to do to create a C++ file for your DLL. (And it's a
lot clearer than me trying to summarize things here).



UnrealScript
------------
Phew! That takes care of the C++ side of things --- now let's briefly look
at the UnrealScript side of the equation (see "dllTrigger.uc" for a concrete
example):

  Class Declaration:
  ------------------
Not too much to say here. Just derive your class from an existing UnrealScript
class, and make sure that:
    - the package name you choose is the same as the name of your DLL.
    - your class name matches the name you put in your C++ files (but without
        the "A" at the start).

  Function Declarations:
  ----------------------
You'll want to let UnrealScript know about your C++ functions by adding the
appropriate 'intrinsic' declarations in your file.

  Calling Your Function:
  ----------------------
Again, this is pretty simple.  Just call your DLL's function like you would
any other function.  There's nothing tricky here!


And that's really all there is to it!  It may seem like a lot here, but if you
look over the included C++ and UnrealScript source code, you'll see that
there's really not that much that you need to worry about.  



KNOWN BUGS/LIMITATIONS:
=======================

There are a *lot* of things I haven't tried yet.  The following list contains
some of the more interesting ones.  Making each of them work may be possible
without any additional effort (i.e. already works), with a little bit of
tweaking, or with a lot of hacking --- I just don't know.  If anyone does get
any of these things to work, I'd be interested in hearing about it.

 - Getting function parameters and return values working. (As I said earlier,
     I think return values are pretty simple, and parameters don't look *too*
     bad either --- but I just haven't had enough time to really play with
     these. I encourage others to try things out and let me know how it goes.)

 - Adding the ability to access C++ class *variables* from UnrealScript,
     instead of just functions.

 - Making the *class* truly intrinsic in the UnrealScript code (as opposed to
     using a non-intrinsic class and intrinsic *functions*).

 - Adding the ability to access functions and variables that are in other
     ("built-in") UnrealScript classes.

 - And much, much more!



CREDITS
=======

It just wouldn't be right if I didn't thank the following people:

  - Mastaba:  for figuring out how to use "unreal -make -h" to generate the
              Unreal C++ header files.  (My stuff doesn't directly use them
              yet, but there's a lot of potential there.)  These files were
              especially helpful in shedding light on the Unreal calling
              convention (it's pretty slick!)
  - Tim Sweeney:  for Unreal.  You're a coding machine.  You rock!
  - John Carmack:  for sparking my interest in 3D engine programming. You
                   rock too. :)



STANDARD DISCLAIMER:
====================

You agree to use all this stuff at your own risk.  I don't take responsibility
for your computer blowing up, you losing your girlfriend, or anything else
that might happen.  I don't expect anything like that *would* happen, but you
never know (blame Murphy).

Oh, and remember, this stuff might all be rendered useless when the next patch
comes out (though hopefully not).

Enjoy.
