fteqcc source
authorMirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>
Sun, 17 Apr 2011 01:17:00 +0000 (04:17 +0300)
committerMirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>
Sun, 17 Apr 2011 01:17:00 +0000 (04:17 +0300)
31 files changed:
misc/mediasource/extra/fteqcc-src/LICENSE [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/Makefile [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/cmdlib.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/comprout.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/execloop.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/gui.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/hash.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/hash.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/initlib.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/pr_comp.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/pr_edict.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/pr_exec.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/pr_multi.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/pr_x86.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/progsint.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/progslib.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/progtype.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcc.dsp [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcc.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcc_cmdlib.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcc_pr_comp.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcc_pr_lex.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qccgui.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qccguistuff.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qccmain.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcctui.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcd.h [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcd_main.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/qcdecomp.c [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/readme.txt [new file with mode: 0644]
misc/mediasource/extra/fteqcc-src/test.c [new file with mode: 0644]

diff --git a/misc/mediasource/extra/fteqcc-src/LICENSE b/misc/mediasource/extra/fteqcc-src/LICENSE
new file mode 100644 (file)
index 0000000..2f3289a
--- /dev/null
@@ -0,0 +1,87 @@
+GNU GENERAL PUBLIC LICENSE
+Version 2, June 1991 
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+Preamble
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. 
+
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. 
+
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. 
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. 
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. 
+
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. 
+
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. 
+
+The precise terms and conditions for copying, distribution and modification follow. 
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". 
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 
+
+1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. 
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 
+
+2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: 
+
+
+a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. 
+
+b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. 
+
+c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) 
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. 
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. 
+
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 
+
+3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: 
+
+a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, 
+
+b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, 
+
+c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) 
+The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. 
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 
+
+4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 
+
+5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 
+
+6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 
+
+7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. 
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. 
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. 
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 
+
+8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 
+
+9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. 
+
+Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 
+
+10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. 
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+
+
+END OF TERMS AND CONDITIONS
diff --git a/misc/mediasource/extra/fteqcc-src/Makefile b/misc/mediasource/extra/fteqcc-src/Makefile
new file mode 100644 (file)
index 0000000..40a721c
--- /dev/null
@@ -0,0 +1,89 @@
+COMMON_OBJS=comprout.o hash.o qcc_cmdlib.o qcd_main.o
+QCC_OBJS=qccmain.o qcc_pr_comp.o qcc_pr_lex.o
+VM_OBJS=pr_exec.o pr_edict.o pr_multi.o initlib.o qcdecomp.o
+GTKGUI_OBJS=qcc_gtk.o qccguistuff.o
+WIN32GUI_OBJS=qccgui.o qccguistuff.o
+TUI_OBJS=qcctui.o
+LIB_OBJS=
+
+CC=gcc -Wall
+
+all: qcc
+
+USEGUI_CFLAGS=
+# set to -DUSEGUI when compiling the GUI
+BASE_CFLAGS=-ggdb $(USEGUI_CFLAGS)
+
+BASE_LDFLAGS=-s
+# set to "" for debugging
+
+DO_CC=$(CC) $(BASE_CFLAGS) -o $@ -c $< $(CFLAGS)
+
+lib: 
+
+R_win_nocyg: $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS)
+       $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 $(BASE_LDFLAGS) $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) -mno-cygwin -mwindows -lcomctl32
+R_nocyg: $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS)
+       $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 $(BASE_LDFLAGS) $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) -mno-cygwin -lcomctl32
+R_win: $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS)
+       $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 $(BASE_LDFLAGS) $(QCC_OBJS) $(COMMON_OBJS) $(WIN32GUI_OBJS) -mwindows -lcomctl32
+
+win_nocyg:
+       $(MAKE) USEGUI_CFLAGS="-DUSEGUI -DQCCONLY" R_win_nocyg
+nocyg:
+       $(MAKE) USEGUI_CFLAGS="-DUSEGUI -DQCCONLY" R_nocyg
+win:
+       $(MAKE) USEGUI_CFLAGS="-DUSEGUI -DQCCONLY" R_win
+
+R_qcc: $(QCC_OBJS) $(COMMON_OBJS) $(TUI_OBJS)
+       $(CC) $(BASE_CFLAGS) -o fteqcc.bin -O3 $(BASE_LDFLAGS) $(QCC_OBJS) $(TUI_OBJS) $(COMMON_OBJS)
+qcc:
+       $(MAKE) USEGUI_CFLAGS="" R_qcc
+
+qccmain.o: qccmain.c qcc.h
+       $(DO_CC)
+
+qcc_cmdlib.o: qcc_cmdlib.c qcc.h
+       $(DO_CC)
+
+qcc_pr_comp.o: qcc_pr_comp.c qcc.h
+       $(DO_CC)
+
+qcc_pr_lex.o: qcc_pr_lex.c qcc.h
+       $(DO_CC)
+
+comprout.o: comprout.c qcc.h
+       $(DO_CC)
+
+hash.o: hash.c qcc.h
+       $(DO_CC)
+
+qcd_main.o: qcd_main.c qcc.h
+       $(DO_CC)
+
+qccguistuff.o: qccguistuff.c qcc.h
+       $(DO_CC)
+
+qcc_gtk.o: qcc_gtk.c qcc.h
+       $(DO_CC) `pkg-config --cflags gtk+-2.0`
+
+R_gtkgui: $(QCC_OBJS) $(COMMON_OBJS) $(GTKGUI_OBJS)
+       $(CC) $(BASE_CFLAGS) $(USEGUI_CFLAGS) -o fteqccgui.bin -O3 $(GTKGUI_OBJS) $(QCC_OBJS) $(COMMON_OBJS) `pkg-config --libs gtk+-2.0`
+gtkgui:
+       $(MAKE) USEGUI_CFLAGS="-DUSEGUI -DQCCONLY" R_gtkgui
+
+clean:
+       $(RM) fteqcc.bin fteqcc.exe $(QCC_OBJS) $(COMMON_OBJS) $(VM_OBJS) $(GTKGUI_OBJS) $(WIN32GUI_OBJS) $(TUI_OBJS)
+
+qcvm.so: $(QCC_OBJS) $(VM_OBJS) $(COMMON_OBJS)
+       $(CC) $(BASE_CFLAGS) -o $@ -O3 $(BASE_LDFLAGS) $(QCC_OBJS) $(VM_OBJS) $(COMMON_OBJS) -shared
+
+
+test.o: test.c
+       $(DO_CC)
+
+testapp.bin: qcvm.so test.o
+       $(CC) $(BASE_CFLAGS) -o testapp.bin -O3 $(BASE_LDFLAGS) qcvm.so test.o
+
+regressiontest: testapp.bin
+       ./testapp.bin regression.dat -srcfile regression.src
diff --git a/misc/mediasource/extra/fteqcc-src/cmdlib.h b/misc/mediasource/extra/fteqcc-src/cmdlib.h
new file mode 100644 (file)
index 0000000..768d899
--- /dev/null
@@ -0,0 +1,93 @@
+// cmdlib.h
+
+#ifndef __CMDLIB__
+#define __CMDLIB__
+
+#include "progsint.h"
+
+/*#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <io.h>
+
+#ifdef NeXT
+#include <libc.h>
+#endif
+*/
+
+// the dec offsetof macro doesn't work very well...
+#define myoffsetof(type,identifier) ((size_t)&((type *)NULL)->identifier)
+
+
+// set these before calling CheckParm
+extern int myargc;
+extern char **myargv;
+
+//char *strupr (char *in);
+//char *strlower (char *in);
+int QCC_filelength (int handle);
+int QCC_tell (int handle);
+
+int QC_strcasecmp (const char *s1, const char *s2);
+
+#ifdef _MSC_VER
+#define QC_vsnprintf _vsnprintf
+#else
+#define QC_vsnprintf vsnprintf
+#endif
+
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+       #ifndef LIKEPRINTF
+               #define LIKEPRINTF(x) __attribute__((format(printf,x,x+1)))
+       #endif
+#endif
+#ifndef LIKEPRINTF
+#define LIKEPRINTF(x)
+#endif
+
+double I_FloatTime (void);
+
+void   VARGS QCC_Error (int errortype, const char *error, ...) LIKEPRINTF(2);
+int            CheckParm (char *check);
+
+
+int    SafeOpenWrite (char *filename, int maxsize);
+int    SafeOpenRead (char *filename);
+void   SafeRead (int handle, void *buffer, long count);
+void   SafeWrite (int handle, void *buffer, long count);
+void   SafeClose(int handle);
+int SafeSeek(int hand, int ofs, int mode);
+void   *SafeMalloc (long size);
+
+
+long   QCC_LoadFile (char *filename, void **bufferptr);
+void   QCC_SaveFile (char *filename, void *buffer, long count);
+
+void   DefaultExtension (char *path, char *extension);
+void   DefaultPath (char *path, char *basepath);
+void   StripFilename (char *path);
+void   StripExtension (char *path);
+
+void   ExtractFilePath (char *path, char *dest);
+void   ExtractFileBase (char *path, char *dest);
+void   ExtractFileExtension (char *path, char *dest);
+
+long   ParseNum (char *str);
+
+
+char *QCC_COM_Parse (char *data);
+char *QCC_COM_Parse2 (char *data);
+
+extern char    qcc_token[1024];
+extern int             qcc_eof;
+
+
+
+#endif
diff --git a/misc/mediasource/extra/fteqcc-src/comprout.c b/misc/mediasource/extra/fteqcc-src/comprout.c
new file mode 100644 (file)
index 0000000..a2a7a3b
--- /dev/null
@@ -0,0 +1,252 @@
+//compile routines
+
+#include "qcc.h"
+#undef progfuncs
+
+char errorfile[128];
+int errorline;
+
+progfuncs_t *qccprogfuncs;
+
+#include <setjmp.h>
+
+extern int qcc_compileactive;
+jmp_buf qcccompileerror;
+char qcc_gamedir[128];
+void QCC_PR_ResetErrorScope(void);
+
+
+
+#ifdef MINIMAL
+
+#else
+
+int qccalloced;
+int qcchunksize;
+char *qcchunk;
+void *qccHunkAlloc(size_t mem)
+{
+       mem = (mem + 7)&~7;
+
+       qccalloced+=mem;
+       if (qccalloced > qcchunksize)
+               QCC_Error(ERR_INTERNAL, "Compile hunk was filled");
+
+       memset(qcchunk+qccalloced-mem, 0, mem);
+       return qcchunk+qccalloced-mem;
+}
+void qccClearHunk(void)
+{
+       if (qcchunk)
+       {
+               free(qcchunk);
+               qcchunk=NULL;
+       }
+}
+int qccpersisthunk;
+void PostCompile(void)
+{
+       if (!qccpersisthunk)
+               qccClearHunk();
+
+       if (asmfile)
+       {
+               fclose(asmfile);
+               asmfile = NULL;
+       }       
+}
+pbool PreCompile(void)
+{
+       QCC_PR_ResetErrorScope();
+
+       qccClearHunk();
+       strcpy(qcc_gamedir, "");
+       qcchunk = malloc(qcchunksize=128*1024*1024);
+       while(!qcchunk && qcchunksize > 8*1024*1024)
+       {
+               qcchunksize /= 2;
+               qcchunk = malloc(qcchunksize);
+       }
+       qccalloced=0;
+
+       return !!qcchunk;
+}
+
+void QCC_main (int argc, char **argv);
+void QCC_ContinueCompile(void);
+void QCC_FinishCompile(void);
+
+int comp_nump;char **comp_parms;
+//void Editor(char *fname, int line, int numparms, char **compileparms);
+pbool CompileParams(progfuncs_t *progfuncs, int doall, int nump, char **parms)
+{
+       comp_nump = nump;
+       comp_parms = parms;
+       *errorfile = '\0';
+       qccprogfuncs = progfuncs;
+       if (setjmp(qcccompileerror))
+       {
+               PostCompile();
+               if (*errorfile)
+               {
+                       if (!externs->useeditor)
+                               printf("Error in %s on line %i\n", errorfile, errorline);
+                       else
+                               externs->useeditor(progfuncs, errorfile, errorline, nump, parms);
+               }
+               return false;
+       }
+
+       if (!PreCompile())
+               return false;
+       QCC_main(nump, parms);
+
+       while(qcc_compileactive)
+               QCC_ContinueCompile();
+
+       PostCompile();
+
+       return true;
+}
+int Comp_Begin(progfuncs_t *progfuncs, int nump, char **parms)
+{
+       comp_nump = nump;
+       comp_parms = parms;
+       qccprogfuncs = progfuncs;
+       *errorfile = '\0';
+       if (setjmp(qcccompileerror))
+       {
+               PostCompile();
+               if (*errorfile)
+                       externs->useeditor(progfuncs, errorfile, errorline, nump, parms);
+               return false;
+       }
+
+       if (!PreCompile())
+               return false;
+       QCC_main(nump, parms);
+
+       return true;
+}
+int Comp_Continue(progfuncs_t *progfuncs)
+{      
+       qccprogfuncs = progfuncs;
+       if (setjmp(qcccompileerror))
+       {
+               PostCompile();
+               if (*errorfile && externs->useeditor)
+                       externs->useeditor(progfuncs, errorfile, errorline, comp_nump, comp_parms);
+               return false;
+       }
+
+       if (qcc_compileactive)
+               QCC_ContinueCompile();
+       else
+       {
+               PostCompile();
+
+               if (*errorfile && externs->useeditor)
+                       externs->useeditor(progfuncs, errorfile, errorline, comp_nump, comp_parms);
+
+               return false;
+       }
+
+       return true;
+}
+#endif
+pbool CompileFile(progfuncs_t *progfuncs, char *filename)
+{      
+#ifdef MINIMAL
+       return false;
+#else
+       char srcfile[32];
+       char newname[32];
+       static char *p[5];
+       int parms;
+       char *s, *s2;
+       
+       p[0] = NULL;
+       parms = 1;
+       
+       strcpy(newname, filename);
+       s = newname;
+       if (strchr(s+1, '/'))
+       {
+               while(1)
+               {
+                       s2 = strchr(s+1, '/');
+                       if (!s2)
+                       {
+                               *s = '\0';
+                               break;
+                       }
+                       s = s2;
+               }
+               p[parms] = "-src";
+               p[parms+1] = newname;
+               parms+=2;       
+               
+               strcpy(srcfile, s+1);
+               srcfile[strlen(srcfile)-4] = '\0';
+               strcat(srcfile, ".src");
+
+               if (externs->FileSize(qcva("%s/%s", newname, srcfile))>0)
+               {
+                       p[parms] = "-srcfile";
+                       p[parms+1] = srcfile;
+                       parms+=2;
+               }
+       }
+       else
+       {
+               p[parms] = "-srcfile";
+               p[parms+1] = newname;
+               newname[strlen(newname)-4] = '\0';
+               strcat(newname, ".src");
+               parms+=2;
+       }
+//     p[2][strlen(p[2])-4] = '\0';
+//     strcat(p[2], "/");
+
+       while (!CompileParams(progfuncs, true, parms, p))
+       {
+               return false;
+       }
+       return true;
+#endif
+}
+
+int QC_strncasecmp(const char *s1, const char *s2, int n)
+{
+       int             c1, c2;
+       
+       while (1)
+       {
+               c1 = *s1++;
+               c2 = *s2++;
+
+               if (!n--)
+                       return 0;               // strings are equal until end point
+               
+               if (c1 != c2)
+               {
+                       if (c1 >= 'a' && c1 <= 'z')
+                               c1 -= ('a' - 'A');
+                       if (c2 >= 'a' && c2 <= 'z')
+                               c2 -= ('a' - 'A');
+                       if (c1 != c2)
+                               return -1;              // strings not equal
+               }
+               if (!c1)
+                       return 0;               // strings are equal
+       }
+       
+       return -1;
+}
+
+void editbadfile(char *fname, int line)
+{
+       strcpy(errorfile, fname);
+       errorline = line;
+}
+
diff --git a/misc/mediasource/extra/fteqcc-src/execloop.h b/misc/mediasource/extra/fteqcc-src/execloop.h
new file mode 100644 (file)
index 0000000..365c93a
--- /dev/null
@@ -0,0 +1,1141 @@
+//qc execution code.
+//we have two conditions.
+//one allows us to debug and trace through our code, the other doesn't.
+
+//hopefully, the compiler will do a great job at optimising this code for us, where required.
+//if it dosn't, then bum.
+
+//the general overhead should be reduced significantly, and I would be supprised if it did run slower.
+
+//run away loops are checked for ONLY on gotos and function calls. This might give a poorer check, but it will run faster overall.
+
+//Appears to work fine.
+
+#if INTSIZE == 16
+#define cont cont16
+#define reeval reeval16
+#define st st16
+#define pr_statements pr_statements16
+#define fakeop fakeop16
+#define dstatement_t dstatement16_t
+#define sofs signed short
+#define uofs unsigned short
+#elif INTSIZE == 32
+#define cont cont32
+#define reeval reeval32
+#define st st32
+#define pr_statements pr_statements32
+#define fakeop fakeop32
+#define dstatement_t dstatement32_t
+#define sofs signed int
+#define uofs unsigned int
+#elif INTSIZE == 24
+#error INTSIZE should be set to 32.
+#else
+#error Bad cont size
+#endif
+
+#define ENGINEPOINTER(p) ((char*)(p) - progfuncs->stringtable)
+#define QCPOINTER(p) (eval_t *)(p->_int+progfuncs->stringtable)
+#define QCPOINTERM(p) (eval_t *)((p)+progfuncs->stringtable)
+
+//rely upon just st
+{
+#ifdef DEBUGABLE
+cont:  //last statement may have been a breakpoint             
+       s = st-pr_statements;
+       s+=1;
+       s=ShowStep(progfuncs, s);
+       st = pr_statements + s;
+
+reeval:
+#else
+       st++;
+#endif
+
+       switch (st->op)
+       {
+       case OP_ADD_F:
+               OPC->_float = OPA->_float + OPB->_float;
+               break;
+       case OP_ADD_V:
+               OPC->_vector[0] = OPA->_vector[0] + OPB->_vector[0];
+               OPC->_vector[1] = OPA->_vector[1] + OPB->_vector[1];
+               OPC->_vector[2] = OPA->_vector[2] + OPB->_vector[2];
+               break;
+
+       case OP_SUB_F:
+               OPC->_float = OPA->_float - OPB->_float;
+               break;
+       case OP_SUB_V:
+               OPC->_vector[0] = OPA->_vector[0] - OPB->_vector[0];
+               OPC->_vector[1] = OPA->_vector[1] - OPB->_vector[1];
+               OPC->_vector[2] = OPA->_vector[2] - OPB->_vector[2];
+               break;
+
+       case OP_MUL_F:
+               OPC->_float = OPA->_float * OPB->_float;
+               break;
+       case OP_MUL_V:
+               OPC->_float = OPA->_vector[0]*OPB->_vector[0]
+                               + OPA->_vector[1]*OPB->_vector[1]
+                               + OPA->_vector[2]*OPB->_vector[2];
+               break;
+       case OP_MUL_FV:
+               OPC->_vector[0] = OPA->_float * OPB->_vector[0];
+               OPC->_vector[1] = OPA->_float * OPB->_vector[1];
+               OPC->_vector[2] = OPA->_float * OPB->_vector[2];
+               break;
+       case OP_MUL_VF:
+               OPC->_vector[0] = OPB->_float * OPA->_vector[0];
+               OPC->_vector[1] = OPB->_float * OPA->_vector[1];
+               OPC->_vector[2] = OPB->_float * OPA->_vector[2];
+               break;
+
+       case OP_DIV_F:
+               OPC->_float = OPA->_float / OPB->_float;
+               break;
+       case OP_DIV_VF:
+               OPC->_vector[0] = OPB->_float / OPA->_vector[0];
+               OPC->_vector[1] = OPB->_float / OPA->_vector[1];
+               OPC->_vector[2] = OPB->_float / OPA->_vector[2];
+               break;
+
+       case OP_BITAND:
+               OPC->_float = (float)((int)OPA->_float & (int)OPB->_float);
+               break;
+
+       case OP_BITOR:
+               OPC->_float = (float)((int)OPA->_float | (int)OPB->_float);
+               break;
+
+
+       case OP_GE:
+               OPC->_float = (float)(OPA->_float >= OPB->_float);
+               break;
+       case OP_GE_I:
+               OPC->_int = (int)(OPA->_int >= OPB->_int);
+               break;
+       case OP_GE_IF:
+               OPC->_float = (float)(OPA->_int >= OPB->_float);
+               break;
+       case OP_GE_FI:
+               OPC->_float = (float)(OPA->_float >= OPB->_int);
+               break;
+
+       case OP_LE:
+               OPC->_float = (float)(OPA->_float <= OPB->_float);
+               break;
+       case OP_LE_I:
+               OPC->_int = (int)(OPA->_int <= OPB->_int);
+               break;
+       case OP_LE_IF:
+               OPC->_float = (float)(OPA->_int <= OPB->_float);
+               break;
+       case OP_LE_FI:
+               OPC->_float = (float)(OPA->_float <= OPB->_int);
+               break;
+
+       case OP_GT:
+               OPC->_float = (float)(OPA->_float > OPB->_float);
+               break;
+       case OP_GT_I:
+               OPC->_int = (int)(OPA->_int > OPB->_int);
+               break;
+       case OP_GT_IF:
+               OPC->_float = (float)(OPA->_int > OPB->_float);
+               break;
+       case OP_GT_FI:
+               OPC->_float = (float)(OPA->_float > OPB->_int);
+               break;
+
+       case OP_LT:
+               OPC->_float = (float)(OPA->_float < OPB->_float);
+               break;
+       case OP_LT_I:
+               OPC->_int = (int)(OPA->_int < OPB->_int);
+               break;
+       case OP_LT_IF:
+               OPC->_float = (float)(OPA->_int < OPB->_float);
+               break;
+       case OP_LT_FI:
+               OPC->_float = (float)(OPA->_float < OPB->_int);
+               break;
+
+       case OP_AND:
+               OPC->_float = (float)(OPA->_float && OPB->_float);
+               break;
+       case OP_OR:
+               OPC->_float = (float)(OPA->_float || OPB->_float);
+               break;
+
+       case OP_NOT_F:
+               OPC->_float = (float)(!OPA->_float);
+               break;
+       case OP_NOT_V:
+               OPC->_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]);
+               break;
+       case OP_NOT_S:
+               OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string));
+               break;
+       case OP_NOT_FNC:
+               OPC->_float = (float)(!(OPA->function & ~0xff000000));
+               break;
+       case OP_NOT_ENT:
+               OPC->_float = (float)(PROG_TO_EDICT(progfuncs, OPA->edict) == (edictrun_t *)sv_edicts);
+               break;
+
+       case OP_EQ_F:
+               OPC->_float = (float)(OPA->_float == OPB->_float);
+               break;
+       case OP_EQ_IF:
+               OPC->_float = (float)(OPA->_int == OPB->_float);
+               break;
+       case OP_EQ_FI:
+               OPC->_float = (float)(OPA->_float == OPB->_int);
+               break;
+
+
+       case OP_EQ_V:
+               OPC->_float = (float)((OPA->_vector[0] == OPB->_vector[0]) &&
+                                       (OPA->_vector[1] == OPB->_vector[1]) &&
+                                       (OPA->_vector[2] == OPB->_vector[2]));
+               break;
+       case OP_EQ_S:
+               if (OPA->string==OPB->string)
+                       OPC->_float = true;
+               else if (!OPA->string)
+               {
+                       if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string))
+                               OPC->_float = true;
+                       else
+                               OPC->_float = false;
+               }
+               else if (!OPB->string)
+               {
+                       if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string))
+                               OPC->_float = true;
+                       else
+                               OPC->_float = false;
+               }
+               else
+                       OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string)));
+               break;
+       case OP_EQ_E:
+               OPC->_float = (float)(OPA->_int == OPB->_int);
+               break;
+       case OP_EQ_FNC:
+               OPC->_float = (float)(OPA->function == OPB->function);
+               break;
+
+
+       case OP_NE_F:
+               OPC->_float = (float)(OPA->_float != OPB->_float);
+               break;
+       case OP_NE_V:
+               OPC->_float = (float)((OPA->_vector[0] != OPB->_vector[0]) ||
+                                       (OPA->_vector[1] != OPB->_vector[1]) ||
+                                       (OPA->_vector[2] != OPB->_vector[2]));
+               break;
+       case OP_NE_S:
+               if (OPA->string==OPB->string)
+                       OPC->_float = false;
+               else if (!OPA->string)
+               {
+                       if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string)))
+                               OPC->_float = false;
+                       else
+                               OPC->_float = true;
+               }
+               else if (!OPB->string)
+               {
+                       if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string))
+                               OPC->_float = false;
+                       else
+                               OPC->_float = true;
+               }
+               else
+                       OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string)));             
+               break;
+       case OP_NE_E:
+               OPC->_float = (float)(OPA->_int != OPB->_int);
+               break;
+       case OP_NE_FNC:
+               OPC->_float = (float)(OPA->function != OPB->function);
+               break;
+
+//==================
+       case OP_STORE_IF:
+               OPB->_float = (float)OPA->_int;
+               break;
+       case OP_STORE_FI:
+               OPB->_int = (int)OPA->_float;
+               break;
+               
+       case OP_STORE_F:
+       case OP_STORE_ENT:
+       case OP_STORE_FLD:              // integers
+       case OP_STORE_S:
+       case OP_STORE_I:
+       case OP_STORE_FNC:              // pointers
+       case OP_STORE_P:
+               OPB->_int = OPA->_int;
+               break;
+       case OP_STORE_V:
+               OPB->_vector[0] = OPA->_vector[0];
+               OPB->_vector[1] = OPA->_vector[1];
+               OPB->_vector[2] = OPA->_vector[2];
+               break;
+
+       //store a value to a pointer
+       case OP_STOREP_IF:
+               if ((unsigned int)OPB->_int >= addressableused)
+               {
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               }
+               ptr = QCPOINTER(OPB);
+               ptr->_float = (float)OPA->_int;
+               break;
+       case OP_STOREP_FI:
+               if ((unsigned int)OPB->_int >= addressableused)
+               {
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               }
+               ptr = QCPOINTER(OPB);
+               ptr->_int = (int)OPA->_float;
+               break;
+       case OP_STOREP_I:
+               if ((unsigned int)OPB->_int >= addressableused)
+               {
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               }
+               ptr = QCPOINTER(OPB);
+               ptr->_int = OPA->_int;
+               break;
+       case OP_STOREP_F:
+       case OP_STOREP_ENT:
+       case OP_STOREP_FLD:             // integers
+       case OP_STOREP_S:
+       case OP_STOREP_FNC:             // pointers
+               if ((unsigned int)OPB->_int >= addressableused)
+               {
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               }
+               ptr = QCPOINTER(OPB);
+               ptr->_int = OPA->_int;
+               break;
+       case OP_STOREP_V:
+               if ((unsigned int)OPB->_int >= addressableused)
+               {
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               }
+               ptr = QCPOINTER(OPB);
+               ptr->_vector[0] = OPA->_vector[0];
+               ptr->_vector[1] = OPA->_vector[1];
+               ptr->_vector[2] = OPA->_vector[2];
+               break;
+
+       case OP_STOREP_C:       //store character in a string
+               if ((unsigned int)OPB->_int >= addressableused)
+               {
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               }
+               ptr = QCPOINTER(OPB);
+               *(unsigned char *)ptr = (char)OPA->_float;
+               break;
+
+       case OP_MULSTORE_F: // f *= f
+               OPB->_float *= OPA->_float;
+               break;
+       case OP_MULSTORE_V: // v *= f
+               OPB->_vector[0] *= OPA->_float;
+               OPB->_vector[1] *= OPA->_float;
+               OPB->_vector[2] *= OPA->_float;
+               break;
+       case OP_MULSTOREP_F: // e.f *= f
+               if ((unsigned int)OPB->_int >= addressableused)
+               {
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               }
+               ptr = QCPOINTER(OPB);
+               OPC->_float = (ptr->_float *= OPA->_float);
+               break;
+       case OP_MULSTOREP_V: // e.v *= f
+               ptr = QCPOINTER(OPB);
+               OPC->_vector[0] = (ptr->_vector[0] *= OPA->_float);
+               OPC->_vector[0] = (ptr->_vector[1] *= OPA->_float);
+               OPC->_vector[0] = (ptr->_vector[2] *= OPA->_float);
+               break;
+
+       case OP_DIVSTORE_F: // f /= f
+               OPB->_float /= OPA->_float;
+               break;
+       case OP_DIVSTOREP_F: // e.f /= f
+               ptr = QCPOINTER(OPB);
+               OPC->_float = (ptr->_float /= OPA->_float);
+               break;
+
+       case OP_ADDSTORE_F: // f += f
+               OPB->_float += OPA->_float;
+               break;
+       case OP_ADDSTORE_V: // v += v
+               OPB->_vector[0] += OPA->_vector[0];
+               OPB->_vector[1] += OPA->_vector[1];
+               OPB->_vector[2] += OPA->_vector[2];
+               break;
+       case OP_ADDSTOREP_F: // e.f += f
+               ptr = QCPOINTER(OPB);
+               OPC->_float = (ptr->_float += OPA->_float);
+               break;
+       case OP_ADDSTOREP_V: // e.v += v
+               ptr = QCPOINTER(OPB);
+               OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]);
+               OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]);
+               OPC->_vector[2] = (ptr->_vector[2] += OPA->_vector[2]);
+               break;
+
+       case OP_SUBSTORE_F: // f -= f
+               OPB->_float -= OPA->_float;
+               break;
+       case OP_SUBSTORE_V: // v -= v
+               OPB->_vector[0] -= OPA->_vector[0];
+               OPB->_vector[1] -= OPA->_vector[1];
+               OPB->_vector[2] -= OPA->_vector[2];
+               break;
+       case OP_SUBSTOREP_F: // e.f -= f
+               ptr = QCPOINTER(OPB);
+               OPC->_float = (ptr->_float -= OPA->_float);
+               break;
+       case OP_SUBSTOREP_V: // e.v -= v
+               ptr = QCPOINTER(OPB);
+               OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]);
+               OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]);
+               OPC->_vector[2] = (ptr->_vector[2] -= OPA->_vector[2]);
+               break;
+
+
+       //get a pointer to a field var
+       case OP_ADDRESS:
+               if ((unsigned)OPA->edict >= (unsigned)maxedicts)
+               {
+#ifndef DEBUGABLE
+                       pr_trace++;
+                       printf("OP_ADDRESS references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
+                       st--;
+                       goto cont;
+#else
+                       PR_RunError (progfuncs, "OP_ADDRESS references invalid entity in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
+#endif
+               }
+               ed = PROG_TO_EDICT(progfuncs, OPA->edict);
+#ifdef PARANOID
+               NUM_FOR_EDICT(ed);              // make sure it's in range
+#endif
+               if (!ed || ed->readonly)
+               {
+                       pr_xstatement = st-pr_statements;
+#ifndef DEBUGABLE
+                       //boot it over to the debugger
+                       pr_trace++;
+                       printf("assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
+                       st--;
+                       goto cont;
+#else
+                       {
+                               ddef16_t *d16;
+                               fdef_t *f;
+                               d16 = ED_GlobalAtOfs16(progfuncs, st->a);
+                               f = ED_FieldAtOfs(progfuncs, OPB->_int + progfuncs->fieldadjust);
+                               PR_RunError (progfuncs, "assignment to read-only entity in %s (%s.%s)", PR_StringToNative(progfuncs, pr_xfunction->s_name), PR_StringToNative(progfuncs, d16->s_name), f?f->name:NULL);
+                       }
+#endif
+               }
+
+//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods.
+//             if (ed->isfree)
+//             {
+//                     pr_xstatement = st-pr_statements;
+//                     PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name);
+//             }
+               OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust));
+               break;
+
+       //load a field to a value
+       case OP_LOAD_I:
+       case OP_LOAD_F:
+       case OP_LOAD_FLD:
+       case OP_LOAD_ENT:
+       case OP_LOAD_S:
+       case OP_LOAD_FNC:
+               if ((unsigned)OPA->edict >= (unsigned)maxedicts)
+                       PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               ed = PROG_TO_EDICT(progfuncs, OPA->edict);
+#ifdef PARANOID
+               NUM_FOR_EDICT(ed);              // make sure it's in range
+#endif
+               ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust);
+               OPC->_int = ptr->_int;
+               break;
+
+       case OP_LOAD_V:
+               if ((unsigned)OPA->edict >= (unsigned)maxedicts)
+                       PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name);
+               ed = PROG_TO_EDICT(progfuncs, OPA->edict);
+#ifdef PARANOID
+               NUM_FOR_EDICT(ed);              // make sure it's in range
+#endif
+               ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust);
+               OPC->_vector[0] = ptr->_vector[0];
+               OPC->_vector[1] = ptr->_vector[1];
+               OPC->_vector[2] = ptr->_vector[2];
+               break;  
+               
+//==================
+
+       case OP_IFNOT_S:
+               RUNAWAYCHECK();
+               if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string))
+                       st += (sofs)st->b - 1;  // offset the s++
+               break;
+
+       case OP_IFNOT_F:
+               RUNAWAYCHECK();
+               if (!OPA->_float)
+                       st += (sofs)st->b - 1;  // offset the s++
+               break;
+
+       case OP_IFNOT:
+               RUNAWAYCHECK();
+               if (!OPA->_int)
+                       st += (sofs)st->b - 1;  // offset the s++
+               break;
+
+       case OP_IF_S:
+               RUNAWAYCHECK();
+               if (OPA->string && PR_StringToNative(progfuncs, OPA->string))
+                       st += (sofs)st->b - 1;  // offset the s++
+               break;
+
+       case OP_IF_F:
+               RUNAWAYCHECK();
+               if (OPA->_int)
+                       st += (sofs)st->b - 1;  // offset the s++
+               break;
+
+       case OP_IF:
+               RUNAWAYCHECK();
+               if (OPA->_int)
+                       st += (sofs)st->b - 1;  // offset the s++
+               break;
+               
+       case OP_GOTO:
+               RUNAWAYCHECK();
+               st += (sofs)st->a - 1;  // offset the s++
+               break;
+
+       case OP_CALL8H:
+       case OP_CALL7H:
+       case OP_CALL6H:
+       case OP_CALL5H:
+       case OP_CALL4H:
+       case OP_CALL3H:
+       case OP_CALL2H:
+               G_VECTOR(OFS_PARM1)[0] = OPC->_vector[0];
+               G_VECTOR(OFS_PARM1)[1] = OPC->_vector[1];
+               G_VECTOR(OFS_PARM1)[2] = OPC->_vector[2];
+       case OP_CALL1H:
+               G_VECTOR(OFS_PARM0)[0] = OPB->_vector[0];
+               G_VECTOR(OFS_PARM0)[1] = OPB->_vector[1];
+               G_VECTOR(OFS_PARM0)[2] = OPB->_vector[2];
+
+       case OP_CALL8:
+       case OP_CALL7:
+       case OP_CALL6:
+       case OP_CALL5:
+       case OP_CALL4:
+       case OP_CALL3:
+       case OP_CALL2:
+       case OP_CALL1:
+       case OP_CALL0:
+               RUNAWAYCHECK();
+               pr_xstatement = st-pr_statements;
+
+
+               if (st->op > OP_CALL8)
+                       pr_argc = st->op - (OP_CALL1H-1);
+               else
+                       pr_argc = st->op - OP_CALL0;
+               fnum = OPA->function;
+               if ((fnum & ~0xff000000)==0)
+               {
+                       pr_trace++;
+                       printf("NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name);
+#ifndef DEBUGABLE
+                       goto cont;
+#endif
+                       break;
+               }
+/*
+{
+       static char buffer[1024*1024*8];
+       int size = sizeof buffer;
+               progfuncs->save_ents(progfuncs, buffer, &size, 0);
+}*/
+
+
+               p=pr_typecurrent;
+//about to switch. needs caching.
+
+               //if it's an external call, switch now (before any function pointers are used)
+               PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p);
+               PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24);
+
+               newf = &pr_functions[fnum & ~0xff000000];
+
+               if (newf->first_statement < 0)
+               {       // negative statements are built in functions
+
+if (pr_typecurrent != 0)
+{
+       PR_MoveParms(progfuncs, 0, pr_typecurrent);
+       PR_SwitchProgs(progfuncs, 0);
+}
+                       i = -newf->first_statement;
+//                     p = pr_typecurrent;
+                       progfuncs->lastcalledbuiltinnumber = i;
+                       if (i < externs->numglobalbuiltins)
+                       {
+                               prinst->numtempstringsstack = prinst->numtempstrings;
+                               (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals);
+                               if (prinst->continuestatement!=-1)
+                               {
+                                       st=&pr_statements[prinst->continuestatement];
+                                       prinst->continuestatement=-1;
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               i -= externs->numglobalbuiltins;
+                               if (i >= current_progstate->numbuiltins)
+                               {
+//                                     if (newf->first_statement == -0x7fffffff)
+//                                             ((builtin_t)newf->profile) (progfuncs, (struct globalvars_s *)current_progstate->globals);
+//                                     else
+                                               PR_RunError (progfuncs, "Bad builtin call number - %i", -newf->first_statement);
+                               }
+                               else
+                                       current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals);
+                       }
+                       PR_MoveParms(progfuncs, p, pr_typecurrent);
+//                     memcpy(&pr_progstate[p].globals[OFS_RETURN], &current_progstate->globals[OFS_RETURN], sizeof(vec3_t));
+                       PR_SwitchProgs(progfuncs, (progsnum_t)p);
+
+//#ifndef DEBUGABLE    //decide weather non debugger wants to start debugging.
+                       s = st-pr_statements;
+                       goto restart;
+//#endif
+//                     break;
+               }
+//             PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent);
+//             PR_SwitchProgs((OPA->function & 0xff000000)>>24);
+               s = PR_EnterFunction (progfuncs, newf, p);
+               st = &pr_statements[s];
+               
+               goto restart;
+//             break;
+
+       case OP_DONE:
+       case OP_RETURN:
+
+               RUNAWAYCHECK();
+
+               pr_globals[OFS_RETURN] = pr_globals[st->a];
+               pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
+               pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
+/*
+{
+       static char buffer[1024*1024*8];
+       int size = sizeof buffer;
+               progfuncs->save_ents(progfuncs, buffer, &size, 0);
+}
+*/
+               s = PR_LeaveFunction (progfuncs);
+               st = &pr_statements[s];         
+               if (pr_depth == prinst->exitdepth)
+               {               
+                       return;         // all done
+               }
+               goto restart;
+//             break;
+
+       case OP_STATE:
+               externs->stateop(progfuncs, OPA->_float, OPB->function);
+               break;
+
+       case OP_ADD_I:          
+               OPC->_int = OPA->_int + OPB->_int;
+               break;
+       case OP_ADD_FI:
+               OPC->_float = OPA->_float + (float)OPB->_int;
+               break;
+       case OP_ADD_IF:
+               OPC->_float = (float)OPA->_int + OPB->_float;
+               break;
+  
+       case OP_SUB_I:
+               OPC->_int = OPA->_int - OPB->_int;
+               break;
+       case OP_SUB_FI:
+               OPC->_float = OPA->_float - (float)OPB->_int;
+               break;
+       case OP_SUB_IF:
+               OPC->_float = (float)OPA->_int - OPB->_float;
+               break;
+
+       case OP_CONV_ITOF:
+               OPC->_float = (float)OPA->_int;
+               break;
+       case OP_CONV_FTOI:
+               OPC->_int = (int)OPA->_float;
+               break;
+
+       case OP_CP_ITOF:
+               ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int);
+               OPC->_float = (float)ptr->_int;
+               break;
+
+       case OP_CP_FTOI:
+               ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int);
+               OPC->_int = (int)ptr->_float;
+               break;
+
+       case OP_BITAND_I:
+               OPC->_int = (OPA->_int & OPB->_int);
+               break;
+       
+       case OP_BITOR_I:
+               OPC->_int = (OPA->_int | OPB->_int);
+               break;
+
+       case OP_MUL_I:          
+               OPC->_int = OPA->_int * OPB->_int;
+               break;
+       case OP_DIV_I:
+               if (OPB->_int == 0)     //no division by zero allowed...
+                       OPC->_int = 0;
+               else
+                       OPC->_int = OPA->_int / OPB->_int;
+               break;
+       case OP_EQ_I:
+               OPC->_int = (OPA->_int == OPB->_int);
+               break;
+       case OP_NE_I:
+               OPC->_int = (OPA->_int != OPB->_int);
+               break;
+       
+
+       //array/structure reading/riting.
+       case OP_GLOBALADDRESS:
+               OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
+               break;
+       case OP_POINTER_ADD:    //pointer to 32 bit (remember to *3 for vectors)
+               OPC->_int = OPA->_int + OPB->_int*4;
+               break;
+
+       case OP_LOADA_I:
+       case OP_LOADA_F:
+       case OP_LOADA_FLD:
+       case OP_LOADA_ENT:
+       case OP_LOADA_S:
+       case OP_LOADA_FNC:
+               ptr = (eval_t *)(&OPA->_int + OPB->_int);
+               OPC->_int = ptr->_int;
+               break;
+
+       case OP_LOADA_V:
+               ptr = (eval_t *)(&OPA->_int + OPB->_int);
+               OPC->_vector[0] = ptr->_vector[0];
+               OPC->_vector[1] = ptr->_vector[1];
+               OPC->_vector[2] = ptr->_vector[2];
+               break;
+
+
+
+       case OP_ADD_SF: //(char*)c = (char*)a + (float)b
+               OPC->_int = OPA->_int + (int)OPB->_float;
+               break;
+       case OP_SUB_S:  //(float)c = (char*)a - (char*)b
+               OPC->_int = OPA->_int - OPB->_int;
+               break;
+       case OP_LOADP_C:        //load character from a string
+               ptr = QCPOINTERM(OPA->_int + (int)OPB->_float);
+               OPC->_float = *(unsigned char *)ptr;
+               break;
+       case OP_LOADP_I:
+       case OP_LOADP_F:
+       case OP_LOADP_FLD:
+       case OP_LOADP_ENT:
+       case OP_LOADP_S:
+       case OP_LOADP_FNC:
+               ptr = QCPOINTERM(OPA->_int + OPB->_int);
+               OPC->_int = ptr->_int;
+               break;
+
+       case OP_LOADP_V:
+               ptr = QCPOINTERM(OPA->_int + OPB->_int);
+               OPC->_vector[0] = ptr->_vector[0];
+               OPC->_vector[1] = ptr->_vector[1];
+               OPC->_vector[2] = ptr->_vector[2];
+               break;
+
+       case OP_XOR_I:
+               OPC->_int = OPA->_int ^ OPB->_int;
+               break;
+       case OP_RSHIFT_I:
+               OPC->_int = OPA->_int >> OPB->_int;
+               break;
+       case OP_LSHIFT_I:
+               OPC->_int = OPA->_int << OPB->_int;
+               break;
+
+
+       case OP_FETCH_GBL_F:
+       case OP_FETCH_GBL_S:
+       case OP_FETCH_GBL_E:
+       case OP_FETCH_GBL_FNC:
+               i = (int)OPB->_float;
+               if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
+               {
+                       PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
+               }
+               t = (eval_t *)&pr_globals[(uofs)st->a + i];
+               OPC->_int = t->_int;
+               break;
+       case OP_FETCH_GBL_V:
+               i = (int)OPB->_float;
+               if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int)
+               {
+                       PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i);
+               }
+               t = (eval_t *)&pr_globals[(uofs)st->a
+                       +((int)OPB->_float)*3];
+               OPC->_vector[0] = t->_vector[0];
+               OPC->_vector[1] = t->_vector[1];
+               OPC->_vector[2] = t->_vector[2];
+               break;
+
+       case OP_CSTATE:
+               externs->cstateop(progfuncs, OPA->_float, OPB->_float, fnum);
+               break;
+
+       case OP_CWSTATE:
+               externs->cwstateop(progfuncs, OPA->_float, OPB->_float, fnum);
+               break;
+
+       case OP_THINKTIME:
+               externs->thinktimeop(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, OPA->edict), OPB->_float);
+               break;
+
+
+       case OP_BITSET: // b (+) a
+               OPB->_float = (float)((int)OPB->_float | (int)OPA->_float);
+               break;
+       case OP_BITSETP: // .b (+) a
+               ptr = QCPOINTER(OPB);
+               ptr->_float = (float)((int)ptr->_float | (int)OPA->_float);
+               break;
+       case OP_BITCLR: // b (-) a
+               OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float));
+               break;
+       case OP_BITCLRP: // .b (-) a
+               ptr = QCPOINTER(OPB);
+               ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float));
+               break;
+
+       case OP_RAND0:
+               G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff);
+               break;
+       case OP_RAND1:
+               G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float;
+               break;
+       case OP_RAND2:
+               if(OPA->_float < OPB->_float)
+               {
+                       G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff)
+                               *(OPB->_float-OPA->_float));
+               }
+               else
+               {
+                       G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff)
+                               *(OPA->_float-OPB->_float));
+               }
+               break;
+       case OP_RANDV0:
+               G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff);
+               G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff);
+               G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff);
+               break;
+       case OP_RANDV1:
+               G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0];
+               G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1];
+               G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2];
+               break;
+       case OP_RANDV2:
+               for(i = 0; i < 3; i++)
+               {
+                       if(OPA->_vector[i] < OPB->_vector[i])
+                       {
+                               G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff)
+                                       *(OPB->_vector[i]-OPA->_vector[i]));
+                       }
+                       else
+                       {
+                               G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX)
+                                       *(OPA->_vector[i]-OPB->_vector[i]));
+                       }
+               }
+               break;
+
+
+       case OP_SWITCH_F:
+       case OP_SWITCH_V:
+       case OP_SWITCH_S:
+       case OP_SWITCH_E:
+       case OP_SWITCH_FNC:
+               swtch = OPA;
+               swtchtype = st->op;
+               RUNAWAYCHECK();
+               st += (sofs)st->b - 1;  // offset the st++
+               break;
+       case OP_CASE:
+               switch(swtchtype)
+               {
+               case OP_SWITCH_F:
+                       if (swtch->_float == OPA->_float)
+                       {
+                               RUNAWAYCHECK();
+                               st += (sofs)st->b-1; // -1 to offset the s++
+                       }
+                       break;
+               case OP_SWITCH_E:
+               case OP_SWITCH_FNC:
+                       if (swtch->_int == OPA->_int)
+                       {
+                               RUNAWAYCHECK();
+                               st += (sofs)st->b-1; // -1 to offset the s++
+                       }
+                       break;
+               case OP_SWITCH_S:
+                       if (swtch->_int == OPA->_int)
+                       {
+                               RUNAWAYCHECK();
+                               st += (sofs)st->b-1; // -1 to offset the s++
+                       }
+                       if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both).
+                               break;
+                       if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string)))
+                       {
+                               RUNAWAYCHECK();
+                               st += (sofs)st->b-1; // -1 to offset the s++
+                       }
+                       break;
+               case OP_SWITCH_V:
+                       if (swtch->_vector[0] == OPA->_vector[0] && swtch->_vector[1] == OPA->_vector[1] && swtch->_vector[2] == OPA->_vector[2])
+                       {
+                               RUNAWAYCHECK();
+                               st += (sofs)st->b-1; // -1 to offset the s++
+                       }
+                       break;
+               default:
+                       PR_RunError (progfuncs, "OP_CASE with bad/missing OP_SWITCH %i", swtchtype);
+                       break;
+               }
+               break;
+       case OP_CASERANGE:
+               switch(swtchtype)
+               {
+               case OP_SWITCH_F:
+                       if (swtch->_float >= OPA->_float && swtch->_float <= OPB->_float)
+                       {
+                               RUNAWAYCHECK();
+                               st += (sofs)st->c-1; // -1 to offset the s++
+                       }
+                       break;
+               default:
+                       PR_RunError (progfuncs, "OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype);
+               }
+               break;
+
+
+
+
+
+
+
+
+
+       case OP_BITAND_IF:
+               OPC->_int = (OPA->_int & (int)OPB->_float);
+               break;
+       case OP_BITOR_IF:
+               OPC->_int = (OPA->_int | (int)OPB->_float);
+               break;
+       case OP_BITAND_FI:
+               OPC->_int = ((int)OPA->_float & OPB->_int);
+               break;
+       case OP_BITOR_FI:
+               OPC->_int = ((int)OPA->_float | OPB->_int);
+               break;
+
+       case OP_MUL_IF:
+               OPC->_float = (OPA->_int * OPB->_float);
+               break;
+       case OP_MUL_FI:
+               OPC->_float = (OPA->_float * OPB->_int);
+               break;
+
+       case OP_MUL_VI:
+               OPC->_vector[0] = OPA->_vector[0] * OPB->_int;
+               OPC->_vector[1] = OPA->_vector[0] * OPB->_int;
+               OPC->_vector[2] = OPA->_vector[0] * OPB->_int;
+               break;
+       case OP_MUL_IV:
+               OPC->_vector[0] = OPB->_int * OPA->_vector[0];
+               OPC->_vector[1] = OPB->_int * OPA->_vector[1];
+               OPC->_vector[2] = OPB->_int * OPA->_vector[2];
+               break;
+
+       case OP_DIV_IF:
+               OPC->_float = (OPA->_int / OPB->_float);
+               break;
+       case OP_DIV_FI:
+               OPC->_float = (OPA->_float / OPB->_int);
+               break;
+
+       case OP_AND_I:
+               OPC->_int = (OPA->_int && OPB->_int);
+               break;
+       case OP_OR_I:
+               OPC->_int = (OPA->_int || OPB->_int);
+               break;
+
+       case OP_AND_IF:
+               OPC->_int = (OPA->_int && OPB->_float);
+               break;
+       case OP_OR_IF:
+               OPC->_int = (OPA->_int || OPB->_float);
+               break;
+
+       case OP_AND_FI:
+               OPC->_int = (OPA->_float && OPB->_int);
+               break;
+       case OP_OR_FI:
+               OPC->_int = (OPA->_float || OPB->_int);
+               break;
+
+       case OP_NOT_I:
+               OPC->_int = !OPA->_int;
+               break;
+
+       case OP_NE_IF:
+               OPC->_int = (OPA->_int != OPB->_float);
+               break;
+       case OP_NE_FI:
+               OPC->_int = (OPA->_float != OPB->_int);
+               break;
+
+       case OP_GSTOREP_I:
+       case OP_GSTOREP_F:
+       case OP_GSTOREP_ENT:
+       case OP_GSTOREP_FLD:            // integers
+       case OP_GSTOREP_S:
+       case OP_GSTOREP_FNC:            // pointers
+       case OP_GSTOREP_V:
+       case OP_GADDRESS:
+       case OP_GLOAD_I:
+       case OP_GLOAD_F:
+       case OP_GLOAD_FLD:
+       case OP_GLOAD_ENT:
+       case OP_GLOAD_S:
+       case OP_GLOAD_FNC:
+               pr_xstatement = st-pr_statements;
+               PR_RunError(progfuncs, "Extra opcode not implemented\n");
+               break;
+
+       case OP_BOUNDCHECK:
+               if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b)
+               {
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int);
+               }
+               break;
+/*     case OP_PUSH:
+               OPC->_int = ENGINEPOINTER(&localstack[localstack_used+pr_spushed]);
+               pr_spushed += OPA->_int;
+               if (pr_spushed + localstack_used >= LOCALSTACK_SIZE)
+               {
+                       pr_spushed = 0;
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError(progfuncs, "Progs pushed too much");
+               }
+               break;
+       case OP_POP:
+               pr_spushed -= OPA->_int;
+               if (pr_spushed < 0)
+               {
+                       pr_spushed = 0;
+                       pr_xstatement = st-pr_statements;
+                       PR_RunError(progfuncs, "Progs poped more than it pushed");
+               }
+               break;
+*/
+       default:                                        
+               if (st->op & 0x8000)    //break point!
+               {
+                       pr_xstatement = s = st-pr_statements;
+
+                       printf("Break point hit in %s.\n", pr_xfunction->s_name+progfuncs->stringtable);
+                       if (pr_trace<1)
+                               pr_trace=1;     //this is what it's for
+
+                       s = ShowStep(progfuncs, s);
+                       st = &pr_statements[s]; //let the user move execution
+                       pr_xstatement = s = st-pr_statements;
+
+#if 0  //fakeop stuff - not practical, the rest of the code is more optimised, st needs to point at the correct statement
+                       memcpy(&fakeop, st, sizeof(dstatement_t));      //don't hit the new statement as a break point, cos it's probably the same one.
+                       fakeop.op &= ~0x8000;
+                       st = &fakeop;   //a little remapping...
+#else
+                       st->op &= ~0x8000;      //just remove the breakpoint and go around again, but this time in the debugger.
+#endif
+
+                       goto reeval;    //reexecute
+               }
+               pr_xstatement = st-pr_statements;
+               PR_RunError (progfuncs, "Bad opcode %i", st->op);
+       }
+}
+
+
+#undef cont
+#undef reeval
+#undef st
+#undef pr_statements
+#undef fakeop
+#undef dstatement_t
+#undef sofs
+#undef uofs
+
+#undef ENGINEPOINTER
+#undef QCPOINTER
+#undef QCPOINTERM
+
diff --git a/misc/mediasource/extra/fteqcc-src/gui.h b/misc/mediasource/extra/fteqcc-src/gui.h
new file mode 100644 (file)
index 0000000..66ad9c5
--- /dev/null
@@ -0,0 +1,21 @@
+void GoToDefinition(char *name);
+void EditFile(char *name, int line);
+
+void GUI_SetDefaultOpts(void);
+int GUI_BuildParms(char *args, char **argv);
+
+unsigned char *QCC_ReadFile (char *fname, void *buffer, int len);
+int QCC_FileSize (char *fname);
+pbool QCC_WriteFile (char *name, void *data, int len);
+void GUI_DialogPrint(char *title, char *text);
+
+extern char parameters[16384];
+
+extern char progssrcname[256];
+extern char progssrcdir[256];
+
+extern pbool fl_hexen2;
+extern pbool fl_autohighlight;
+extern pbool fl_compileonstart;
+extern pbool fl_showall;
+extern pbool fl_log;
diff --git a/misc/mediasource/extra/fteqcc-src/hash.c b/misc/mediasource/extra/fteqcc-src/hash.c
new file mode 100644 (file)
index 0000000..2b7b912
--- /dev/null
@@ -0,0 +1,272 @@
+#include "hash.h"
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#ifndef stricmp 
+#define stricmp strcasecmp
+#endif
+#endif
+
+// hash init assumes we get clean memory
+void Hash_InitTable(hashtable_t *table, int numbucks, void *mem)
+{
+       table->numbuckets = numbucks;
+       table->bucket = (bucket_t **)mem;
+}
+
+int Hash_Key(const char *name, int modulus)
+{      //fixme: optimize.
+       unsigned int key;
+       for (key=0;*name; name++)
+               key += ((key<<3) + (key>>28) + *name);
+               
+       return (int)(key%modulus);
+}
+int Hash_KeyInsensative(const char *name, int modulus)
+{      //fixme: optimize.
+       unsigned int key;
+       for (key=0;*name; name++)
+       {
+               if (*name >= 'A' && *name <= 'Z')
+                       key += ((key<<3) + (key>>28) + (*name-'A'+'a'));
+               else
+                       key += ((key<<3) + (key>>28) + *name);
+       }
+               
+       return (int)(key%modulus);
+}
+
+void *Hash_Get(hashtable_t *table, const char *name)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+void *Hash_GetInsensative(hashtable_t *table, const char *name)
+{
+       int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (!stricmp(name, buck->key.string))
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+void *Hash_GetKey(hashtable_t *table, int key)
+{
+       int bucknum = key%table->numbuckets;
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (buck->key.value == key)
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+void *Hash_GetNext(hashtable_t *table, char *name, void *old)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+               {
+                       if (buck->data == old)  //found the old one
+                               break;
+               }
+
+               buck = buck->next;
+       }
+       if (!buck)
+               return NULL;
+
+       buck = buck->next;//don't return old
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+void *Hash_GetNextInsensative(hashtable_t *table, char *name, void *old)
+{
+       int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+       bucket_t *buck;
+
+       buck = table->bucket[bucknum];
+
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+               {
+                       if (buck->data == old)  //found the old one
+                               break;
+               }
+
+               buck = buck->next;
+       }
+       if (!buck)
+               return NULL;
+
+       buck = buck->next;//don't return old
+       while(buck)
+       {
+               if (!STRCMP(name, buck->key.string))
+                       return buck->data;
+
+               buck = buck->next;
+       }
+       return NULL;
+}
+
+
+void *Hash_Add(hashtable_t *table, char *name, void *data, bucket_t *buck)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+
+       buck->data = data;
+       buck->key.string = name;
+       buck->next = table->bucket[bucknum];
+       table->bucket[bucknum] = buck;
+
+       return buck;
+}
+void *Hash_AddInsensative(hashtable_t *table, char *name, void *data, bucket_t *buck)
+{
+       int bucknum = Hash_KeyInsensative(name, table->numbuckets);
+
+       buck->data = data;
+       buck->key.string = name;
+       buck->next = table->bucket[bucknum];
+       table->bucket[bucknum] = buck;
+
+       return buck;
+}
+void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck)
+{
+       int bucknum = key%table->numbuckets;
+
+       buck->data = data;
+       buck->key.value = key;
+       buck->next = table->bucket[bucknum];
+       table->bucket[bucknum] = buck;
+
+       return buck;
+}
+
+void Hash_Remove(hashtable_t *table, char *name)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+       bucket_t *buck; 
+
+       buck = table->bucket[bucknum];
+       if(!buck)
+               return;
+
+       if (!STRCMP(name, buck->key.string))
+       {
+               table->bucket[bucknum] = buck->next;
+               return;
+       }
+
+
+       while(buck->next)
+       {
+               if (!STRCMP(name, buck->next->key.string))
+               {
+                       buck->next = buck->next->next;
+                       return;
+               }
+
+               buck = buck->next;
+       }
+       return;
+}
+
+void Hash_RemoveData(hashtable_t *table, char *name, void *data)
+{
+       int bucknum = Hash_Key(name, table->numbuckets);
+       bucket_t *buck; 
+
+       buck = table->bucket[bucknum];
+       if(!buck)
+               return;
+
+       if (buck->data == data)
+               if (!STRCMP(name, buck->key.string))
+               {
+                       table->bucket[bucknum] = buck->next;
+                       return;
+               }
+
+
+       while(buck->next)
+       {
+               if (buck->next->data == data)
+                       if (!STRCMP(name, buck->next->key.string))
+                       {
+                               buck->next = buck->next->next;
+                               return;
+                       }
+
+               buck = buck->next;
+       }
+       return;
+}
+
+
+void Hash_RemoveKey(hashtable_t *table, int key)
+{
+       int bucknum = key%table->numbuckets;
+       bucket_t *buck; 
+
+       buck = table->bucket[bucknum];
+       if(!buck)
+               return;
+
+       if (buck->key.value == key)
+       {
+               table->bucket[bucknum] = buck->next;
+               return;
+       }
+
+
+       while(buck->next)
+       {
+               if (buck->next->key.value == key)
+               {
+                       buck->next = buck->next->next;
+                       return;
+               }
+
+               buck = buck->next;
+       }
+       return;
+}
diff --git a/misc/mediasource/extra/fteqcc-src/hash.h b/misc/mediasource/extra/fteqcc-src/hash.h
new file mode 100644 (file)
index 0000000..778e67a
--- /dev/null
@@ -0,0 +1,38 @@
+//=============================
+//David's hash tables
+//string based.
+
+#ifndef HASH_H__
+#define HASH_H__
+
+#define Hash_BytesForBuckets(b) (sizeof(bucket_t)*b)
+
+#define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1))    //saves about 2-6 out of 120 - expansion of idea from fastqcc
+typedef struct bucket_s {
+       void *data;
+       union {
+               const char *string;
+               int value;
+       } key;
+       struct bucket_s *next;
+} bucket_t;
+typedef struct hashtable_s {
+       int numbuckets;
+       bucket_t **bucket;
+} hashtable_t;
+
+void Hash_InitTable(hashtable_t *table, int numbucks, void *mem);      //mem must be 0 filled. (memset(mem, 0, size))
+int Hash_Key(const char *name, int modulus);
+void *Hash_Get(hashtable_t *table, const char *name);
+void *Hash_GetInsensative(hashtable_t *table, const char *name);
+void *Hash_GetKey(hashtable_t *table, int key);
+void *Hash_GetNext(hashtable_t *table, char *name, void *old);
+void *Hash_GetNextInsensative(hashtable_t *table, char *name, void *old);
+void *Hash_Add(hashtable_t *table, char *name, void *data, bucket_t *buck);
+void *Hash_AddInsensative(hashtable_t *table, char *name, void *data, bucket_t *buck);
+void Hash_Remove(hashtable_t *table, char *name);
+void Hash_RemoveData(hashtable_t *table, char *name, void *data);
+void Hash_RemoveKey(hashtable_t *table, int key);
+void *Hash_AddKey(hashtable_t *table, int key, void *data, bucket_t *buck);
+
+#endif
diff --git a/misc/mediasource/extra/fteqcc-src/initlib.c b/misc/mediasource/extra/fteqcc-src/initlib.c
new file mode 100644 (file)
index 0000000..1ca5728
--- /dev/null
@@ -0,0 +1,834 @@
+#define PROGSUSED
+#include "progsint.h"
+#include <stdlib.h>
+
+typedef struct prmemb_s {
+       struct prmemb_s *prev;
+       int level;
+} prmemb_t;
+void *PRHunkAlloc(progfuncs_t *progfuncs, int ammount)
+{
+       prmemb_t *mem;
+       ammount = sizeof(prmemb_t)+((ammount + 3)&~3);
+       mem = memalloc(ammount); 
+       memset(mem, 0, ammount);
+       mem->prev = memb;
+       if (!memb)
+               mem->level = 1;
+       else
+               mem->level = ((prmemb_t *)memb)->level+1;
+       memb = mem;
+
+       return ((char *)mem)+sizeof(prmemb_t);
+}
+
+int PRHunkMark(progfuncs_t *progfuncs)
+{
+       return ((prmemb_t *)memb)->level;
+}
+void PRHunkFree(progfuncs_t *progfuncs, int mark)
+{
+       prmemb_t *omem;
+       while(memb)
+       {
+               if (memb->level <= mark)
+                       return;
+
+               omem = memb;
+               memb = memb->prev;
+               memfree(omem);
+       }
+       return;
+}
+
+//for 64bit systems. :)
+//addressable memory is memory available to the vm itself for writing.
+//once allocated, it cannot be freed for the lifetime of the VM.
+void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount)
+{
+       ammount = (ammount + 4)&~3;     //round up to 4
+       if (addressableused + ammount > addressablesize)
+               Sys_Error("Not enough addressable memory for progs VM");
+
+       addressableused += ammount;
+
+#ifdef _WIN32
+       if (!VirtualAlloc (addressablehunk, addressableused, MEM_COMMIT, PAGE_READWRITE))
+               Sys_Error("VirtualAlloc failed. Blame windows.");
+#endif
+
+       return &addressablehunk[addressableused-ammount];
+}
+
+void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount)
+{
+       addressableused = 0;
+       if (totalammount < 0)   //flush
+       {
+               totalammount = addressablesize;
+//             return;
+       }
+
+       if (addressablehunk)
+#ifdef _WIN32
+       VirtualFree(addressablehunk, 0, MEM_RELEASE);   //doesn't this look complicated? :p
+       addressablehunk = VirtualAlloc (NULL, totalammount, MEM_RESERVE, PAGE_NOACCESS);
+#else
+       free(addressablehunk);
+       addressablehunk = malloc(totalammount); //linux will allocate-on-use anyway, which is handy.
+//     memset(addressablehunk, 0xff, totalammount);
+#endif
+       if (!addressablehunk)
+               Sys_Error("Out of memory\n");
+       addressablesize = totalammount;
+}
+
+int PR_InitEnts(progfuncs_t *progfuncs, int max_ents)
+{
+       maxedicts = max_ents;
+
+       sv_num_edicts = 0;
+
+       max_fields_size = fields_size;
+
+       prinst->edicttable = PRHunkAlloc(progfuncs, maxedicts*sizeof(struct edicts_s *));
+       sv_edicts = PRHunkAlloc(progfuncs, externs->edictsize);
+       prinst->edicttable[0] = sv_edicts;
+       ((edictrun_t*)prinst->edicttable[0])->fields = PRAddressableAlloc(progfuncs, max_fields_size);
+       QC_ClearEdict(progfuncs, sv_edicts);
+       sv_num_edicts = 1;
+
+       if (externs->entspawn)
+               externs->entspawn((struct edict_s *)sv_edicts, false);
+
+       return max_fields_size;
+}
+edictrun_t tempedict;  //used as a safty buffer
+float tempedictfields[2048];
+
+void PR_Configure (progfuncs_t *progfuncs, int addressable_size, int max_progs)        //can be used to wipe all memory
+{
+       unsigned int i;
+       edictrun_t *e;
+
+//     int a;
+#ifdef QCJIT
+       prinst->usejit = true;
+#endif
+
+       max_fields_size=0;
+       fields_size = 0;
+       progfuncs->stringtable = 0;
+       QC_StartShares(progfuncs);
+       QC_InitShares(progfuncs);
+
+       for ( i=1 ; i<maxedicts; i++)
+       {
+               e = (edictrun_t *)(prinst->edicttable[i]);
+               prinst->edicttable[i] = NULL;
+//             e->entnum = i;
+               if (e)
+                       memfree(e);
+       }
+
+       PRHunkFree(progfuncs, 0);       //clear mem - our hunk may not be a real hunk.
+       if (addressable_size<0)
+               addressable_size = 8*1024*1024;
+       PRAddressableFlush(progfuncs, addressable_size);
+
+       pr_progstate = PRHunkAlloc(progfuncs, sizeof(progstate_t) * max_progs);
+
+/*             for(a = 0; a < max_progs; a++)
+               {
+                       pr_progstate[a].progs = NULL;
+               }               
+*/
+               
+       maxprogs = max_progs;
+       pr_typecurrent=-1;
+
+       prinst->reorganisefields = false;
+
+       maxedicts = 1;
+       prinst->edicttable = &sv_edicts;
+       sv_num_edicts = 1;      //set up a safty buffer so things won't go horribly wrong too often
+       sv_edicts=(struct edict_s *)&tempedict;
+       tempedict.readonly = true;
+       tempedict.fields = tempedictfields;
+       tempedict.isfree = false;
+}
+
+
+
+struct globalvars_s *PR_globals (progfuncs_t *progfuncs, progsnum_t pnum)
+{
+       if (pnum < 0)
+       {
+               if (!current_progstate)
+                       return NULL;    //err.. you've not loaded one yet.
+               return (struct globalvars_s *)current_progstate->globals;
+       }
+       return (struct globalvars_s *)pr_progstate[pnum].globals;
+}
+
+struct entvars_s *PR_entvars (progfuncs_t *progfuncs, struct edict_s *ed)
+{
+       if (((edictrun_t *)ed)->isfree)
+               return NULL;
+
+       return (struct entvars_s *)edvars(ed);
+}
+
+int PR_GetFuncArgCount(progfuncs_t *progfuncs, func_t func)
+{
+       unsigned int pnum;
+       unsigned int fnum;
+       dfunction_t *f;
+
+       pnum = (func & 0xff000000)>>24;
+       fnum = (func & 0x00ffffff);
+
+       if (pnum >= (unsigned)maxprogs || !pr_progstate[pnum].functions)
+               return -1;
+       else if (fnum >= pr_progstate[pnum].progs->numfunctions)
+               return -1;
+       else
+       {
+               f = pr_progstate[pnum].functions + fnum;
+               return f->numparms;
+       }
+}
+
+func_t PR_FindFunc(progfuncs_t *progfuncs, char *funcname, progsnum_t pnum)
+{
+       dfunction_t *f=NULL;
+       if (pnum == PR_ANY)
+       {
+               for (pnum = 0; (unsigned)pnum < maxprogs; pnum++)
+               {
+                       if (!pr_progstate[pnum].progs)
+                               continue;
+                       f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
+                       if (f)
+                               break;
+               }
+       }
+       else if (pnum == PR_ANYBACK)    //run backwards
+       {
+               for (pnum = maxprogs-1; pnum >= 0; pnum--)
+               {
+                       if (!pr_progstate[pnum].progs)
+                               continue;
+                       f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
+                       if (f)
+                               break;
+               }
+       }
+       else
+               f = ED_FindFunction(progfuncs, funcname, &pnum, pnum);
+       if (!f)
+               return 0;
+
+       {
+       ddef16_t *var16;
+       ddef32_t *var32;
+       switch(pr_progstate[pnum].intsize)
+       {
+       case 24:
+       case 16:
+               var16 = ED_FindTypeGlobalFromProgs16(progfuncs, funcname, pnum, ev_function);   //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function.
+               if (!var16)
+                       return (f - pr_progstate[pnum].functions) | (pnum << 24);
+               return *(int *)&pr_progstate[pnum].globals[var16->ofs]; 
+       case 32:
+               var32 = ED_FindTypeGlobalFromProgs32(progfuncs, funcname, pnum, ev_function);   //we must make sure we actually have a function def - 'light' is defined as a field before it is defined as a function.
+               if (!var32)
+                       return (f - pr_progstate[pnum].functions) | (pnum << 24);
+               return *(int *)&pr_progstate[pnum].globals[var32->ofs]; 
+       }
+       Sys_Error("Error with def size (PR_FindFunc)"); 
+       }
+       return 0;
+}
+
+eval_t *PR_FindGlobal(progfuncs_t *progfuncs, char *globname, progsnum_t pnum)
+{
+       unsigned int i;
+       ddef16_t *var16;
+       ddef32_t *var32;
+       if (pnum == PR_CURRENT)
+               pnum = pr_typecurrent;
+       if (pnum == PR_ANY)
+       {
+               eval_t *ev;
+               for (i = 0; i < maxprogs; i++)
+               {
+                       if (!pr_progstate[i].progs)
+                               continue;
+                       ev = PR_FindGlobal(progfuncs, globname, i);
+                       if (ev)
+                               return ev;
+               }
+               return NULL;
+       }
+       if (pnum < 0 || (unsigned)pnum >= maxprogs || !pr_progstate[pnum].progs)
+               return NULL;
+       switch(pr_progstate[pnum].intsize)
+       {
+       case 16:
+       case 24:
+               if (!(var16 = ED_FindGlobalFromProgs16(progfuncs, globname, pnum)))
+                       return NULL;
+
+               return (eval_t *)&pr_progstate[pnum].globals[var16->ofs];
+       case 32:
+               if (!(var32 = ED_FindGlobalFromProgs32(progfuncs, globname, pnum)))
+                       return NULL;
+
+               return (eval_t *)&pr_progstate[pnum].globals[var32->ofs];
+       }
+       Sys_Error("Error with def size (PR_FindGlobal)");
+       return NULL;
+}
+
+void SetGlobalEdict(progfuncs_t *progfuncs, struct edict_s *ed, int ofs)
+{
+       ((int*)pr_globals)[ofs] = EDICT_TO_PROG(progfuncs, ed);
+}
+
+char *PR_VarString (progfuncs_t *progfuncs, int        first)
+{
+       int             i;
+       static char out[1024];
+       char *s;
+       
+       out[0] = 0;
+       for (i=first ; i<pr_argc ; i++)
+       {
+               if (G_STRING(OFS_PARM0+i*3))
+               {
+                       s=G_STRING((OFS_PARM0+i*3)) + progfuncs->stringtable;
+                       strcat (out, s);
+
+//#ifdef PARANOID
+                       if (strlen(out)+1 >= sizeof(out))
+                               Sys_Error("VarString (builtin call ending with strings) exceeded maximum string length of %i chars", sizeof(out));
+//#endif
+               }
+       }
+       return out;
+}
+
+int PR_QueryField (progfuncs_t *progfuncs, unsigned int fieldoffset, etype_t *type, char **name, evalc_t *fieldcache)
+{
+       fdef_t *var;
+       var = ED_FieldAtOfs(progfuncs, fieldoffset);
+       if (!var)
+               return false;
+
+       if (type)
+               *type = var->type & ~(DEF_SAVEGLOBAL|DEF_SHARED);
+       if (name)
+               *name = var->name;
+       if (fieldcache)
+       {
+               fieldcache->ofs32 = var;
+               fieldcache->varname = var->name;
+       }
+               
+       return true;
+}
+
+eval_t *GetEdictFieldValue(progfuncs_t *progfuncs, struct edict_s *ed, char *name, evalc_t *cache)
+{
+       fdef_t *var;
+       if (!cache)
+       {
+               var = ED_FindField(progfuncs, name);
+               if (!var)
+                       return NULL;
+               return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]);
+       }
+       if (!cache->varname)
+       {
+               cache->varname = name;
+               var = ED_FindField(progfuncs, name);            
+               if (!var)
+               {
+                       cache->ofs32 = NULL;
+                       return NULL;
+               }
+               cache->ofs32 = var;
+               cache->varname = var->name;
+               if (!ed)
+                       return (void*)~0;       //something not null
+               return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[var->ofs]);
+       }
+       if (cache->ofs32 == NULL)
+               return NULL;
+       return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[cache->ofs32->ofs]);
+}
+
+struct edict_s *ProgsToEdict (progfuncs_t *progfuncs, int progs)
+{
+       if ((unsigned)progs >= (unsigned)maxedicts)
+       {
+               printf("Bad entity index %i\n", progs);
+               progs = 0;
+       }
+       return (struct edict_s *)PROG_TO_EDICT(progfuncs, progs);
+}
+int EdictToProgs (progfuncs_t *progfuncs, struct edict_s *ed)
+{
+       return EDICT_TO_PROG(progfuncs, ed);
+}
+
+string_t PR_StringToProgs                      (progfuncs_t *progfuncs, char *str)
+{
+       char **ntable;
+       int i, free=-1;
+
+       if (!str)
+               return 0;
+
+//     if (str-progfuncs->stringtable < progfuncs->stringtablesize)
+//             return str - progfuncs->stringtable;
+
+       for (i = prinst->numallocedstrings-1; i >= 0; i--)
+       {
+               if (prinst->allocedstrings[i] == str)
+                       return (string_t)((unsigned int)i | 0x80000000);
+               if (!prinst->allocedstrings[i])
+                       free = i;
+       }
+
+       if (free != -1)
+       {
+               i = free;
+               prinst->allocedstrings[i] = str;
+               return (string_t)((unsigned int)i | 0x80000000);
+       }
+
+       prinst->maxallocedstrings += 1024;
+       ntable = memalloc(sizeof(char*) * prinst->maxallocedstrings); 
+       memcpy(ntable, prinst->allocedstrings, sizeof(char*) * prinst->numallocedstrings);
+       memset(ntable + prinst->numallocedstrings, 0, sizeof(char*) * (prinst->maxallocedstrings - prinst->numallocedstrings));
+       prinst->numallocedstrings = prinst->maxallocedstrings;
+       if (prinst->allocedstrings)
+               memfree(prinst->allocedstrings);
+       prinst->allocedstrings = ntable;
+
+       for (i = prinst->numallocedstrings-1; i >= 0; i--)
+       {
+               if (!prinst->allocedstrings[i])
+               {
+                       prinst->allocedstrings[i] = str;
+                       return (string_t)((unsigned int)i | 0x80000000);
+               }
+       }
+
+       return 0;
+}
+
+char *PR_RemoveProgsString                             (progfuncs_t *progfuncs, string_t str)
+{
+       char *ret;
+
+       //input string is expected to be an allocated string
+       //if its a temp, or a constant, just return NULL.
+       if ((unsigned int)str & 0xc0000000)
+       {
+               if ((unsigned int)str & 0x80000000)
+               {
+                       int i = str & ~0x80000000;
+                       if (i >= prinst->numallocedstrings)
+                       {
+                               pr_trace = 1;
+                               return NULL;
+                       }
+                       if (prinst->allocedstrings[i])
+                       {
+                               ret = prinst->allocedstrings[i];
+                               prinst->allocedstrings[i] = NULL;       //remove it
+                               return ret;
+                       }
+                       else
+                       {
+                               pr_trace = 1;
+                               return NULL;    //urm, was freed...
+                       }
+               }
+       }
+       pr_trace = 1;
+       return NULL;
+}
+
+char *PR_StringToNative                                (progfuncs_t *progfuncs, string_t str)
+{
+       if ((unsigned int)str & 0xc0000000)
+       {
+               if ((unsigned int)str & 0x80000000)
+               {
+                       int i = str & ~0x80000000;
+                       if (i >= prinst->numallocedstrings)
+                       {
+                               pr_trace = 1;
+                               return "";
+                       }
+                       if (prinst->allocedstrings[i])
+                               return prinst->allocedstrings[i];
+                       else
+                       {
+                               pr_trace = 1;
+                               return "";      //urm, was freed...
+                       }
+               }
+               if ((unsigned int)str & 0x40000000)
+               {
+                       int i = str & ~0x40000000;
+                       if (i >= prinst->numtempstrings)
+                       {
+                               pr_trace = 1;
+                               return "";
+                       }
+                       return prinst->tempstrings[i];
+               }
+       }
+
+       if (str >= progfuncs->stringtablesize)
+       {
+               pr_trace = 1;
+               return "";
+       }
+       return progfuncs->stringtable + str;
+}
+
+
+string_t PR_AllocTempString                    (progfuncs_t *progfuncs, char *str)
+{
+       char **ntable;
+       int newmax;
+       int i;
+
+       if (!str)
+               return 0;
+
+       if (prinst->numtempstrings == prinst->maxtempstrings)
+       {
+               newmax = prinst->maxtempstrings += 1024;
+               prinst->maxtempstrings += 1024;
+               ntable = memalloc(sizeof(char*) * newmax);
+               memcpy(ntable, prinst->tempstrings, sizeof(char*) * prinst->numtempstrings);
+               prinst->maxtempstrings = newmax;
+               if (prinst->tempstrings)
+                       memfree(prinst->tempstrings);
+               prinst->tempstrings = ntable;
+       }
+
+       i = prinst->numtempstrings;
+       if (i == 0x10000000)
+               return 0;
+
+       prinst->numtempstrings++;
+
+       prinst->tempstrings[i] = memalloc(strlen(str)+1);
+       strcpy(prinst->tempstrings[i], str);
+
+       return (string_t)((unsigned int)i | 0x40000000);
+}
+
+void PR_FreeTemps                      (progfuncs_t *progfuncs, int depth)
+{
+       int i;
+       if (depth > prinst->numtempstrings)
+       {
+               Sys_Error("QC Temp stack inverted\n");
+               return;
+       }
+       for (i = depth; i < prinst->numtempstrings; i++)
+       {
+               memfree(prinst->tempstrings[i]);
+       }
+
+       prinst->numtempstrings = depth;
+}
+
+
+struct qcthread_s *PR_ForkStack        (progfuncs_t *progfuncs);
+void PR_ResumeThread                   (progfuncs_t *progfuncs, struct qcthread_s *thread);
+void   PR_AbortStack                   (progfuncs_t *progfuncs);
+
+
+void RegisterBuiltin(progfuncs_t *progfncs, char *name, builtin_t func);
+
+progfuncs_t deffuncs = {
+       PROGSTRUCT_VERSION,
+       PR_Configure,
+       PR_LoadProgs,
+       PR_InitEnts,
+       PR_ExecuteProgram,
+       PR_SwitchProgs,
+       PR_globals,
+       PR_entvars,
+       PR_RunError,
+       ED_Print,
+       ED_Alloc,
+       ED_Free,
+
+       EDICT_NUM,
+       NUM_FOR_EDICT,
+
+
+       SetGlobalEdict,
+
+       PR_VarString,
+
+       NULL,
+       PR_FindFunc,
+#ifdef MINIMAL
+       NULL,
+       NULL,
+#else
+       Comp_Begin,
+       Comp_Continue,
+#endif
+
+       filefromprogs,
+       NULL,//filefromnewprogs,
+
+       SaveEnts,
+       LoadEnts,
+
+       SaveEnt,
+       RestoreEnt,
+
+       PR_FindGlobal,
+       ED_NewString,
+       (void*)PRHunkAlloc,
+
+       GetEdictFieldValue,
+       ProgsToEdict,
+       EdictToProgs,
+
+       EvaluateDebugString,
+
+       NULL,
+       PR_StackTrace,
+
+       PR_ToggleBreakpoint,
+       0,
+       NULL,
+#ifdef MINIMAL
+       NULL,
+#else
+       Decompile,
+#endif
+       NULL,
+       NULL,
+       RegisterBuiltin,
+
+       0,
+       0,
+
+       PR_ForkStack,
+       PR_ResumeThread,
+       PR_AbortStack,
+
+       0,
+
+       QC_RegisterFieldVar,
+
+       0,
+       0,
+
+       PR_AllocTempString,
+
+       PR_StringToProgs,
+       PR_StringToNative,
+       0,
+       PR_QueryField,
+       QC_ClearEdict
+};
+#undef printf
+
+//defs incase following structure is not passed.
+struct edict_s *safesv_edicts;
+int safesv_num_edicts;
+double safetime=0;
+
+progexterns_t defexterns = {
+       PROGSTRUCT_VERSION,             
+
+       NULL, //char *(*ReadFile) (char *fname, void *buffer, int len);
+       NULL, //int (*FileSize) (char *fname);  //-1 if file does not exist
+       NULL, //bool (*WriteFile) (char *name, void *data, int len);
+       printf, //void (*printf) (char *, ...);
+       (void*)exit, //void (*Sys_Error) (char *, ...);
+       NULL, //void (*Abort) (char *, ...);
+       sizeof(edictrun_t), //int edictsize;    //size of edict_t
+
+       NULL, //void (*entspawn) (struct edict_s *ent); //ent has been spawned, but may not have all the extra variables (that may need to be set) set
+       NULL, //bool (*entcanfree) (struct edict_s *ent);       //return true to stop ent from being freed
+       NULL, //void (*stateop) (float var, func_t func);
+       NULL,
+       NULL,
+       NULL,
+
+       //used when loading a game
+       NULL, //builtin_t *(*builtinsfor) (int num);    //must return a pointer to the builtins that were used before the state was saved.
+       NULL, //void (*loadcompleate) (int edictsize);  //notification to reset any pointers.
+
+       (void*)malloc, //void *(*memalloc) (int size);  //small string allocation       malloced and freed randomly by the executor. (use memalloc if you want)
+       free, //void (*memfree) (void * mem);
+
+
+       NULL, //builtin_t *globalbuiltins;      //these are available to all progs
+       0, //int numglobalbuiltins;
+
+       PR_NOCOMPILE,
+
+       &safetime, //double *gametime;
+
+       &safesv_edicts, //struct edict_s **sv_edicts;
+       &safesv_num_edicts, //int *sv_num_edicts;
+
+       NULL, //int (*useeditor) (char *filename, int line, int nump, char **parms);
+};
+
+//progfuncs_t *progfuncs = NULL;
+#undef memfree
+#undef prinst
+#undef extensionbuiltin
+#undef field
+#undef shares
+#undef sv_num_edicts
+
+
+#ifdef QCLIBDLL_EXPORTS
+__declspec(dllexport)
+#endif 
+void CloseProgs(progfuncs_t *inst)
+{
+//     extensionbuiltin_t *eb;
+       void (VARGS *f) (void *);
+
+       unsigned int i;
+       edictrun_t *e;
+
+       f = inst->parms->memfree;
+
+       for ( i=1 ; i<inst->maxedicts; i++)
+       {
+               e = (edictrun_t *)(inst->prinst->edicttable[i]);
+               inst->prinst->edicttable[i] = NULL;
+               if (e)
+               {
+//                     e->entnum = i;
+                       f(e);
+               }
+       }
+
+       PRHunkFree(inst, 0);
+
+#ifdef _WIN32
+       VirtualFree(inst->addressablehunk, 0, MEM_RELEASE);     //doesn't this look complicated? :p
+#else
+       free(inst->addressablehunk);
+#endif
+
+/*
+       while(inst->prinst->extensionbuiltin)
+       {
+               eb = inst->prinst->extensionbuiltin->prev;
+               f(inst->prinst->extensionbuiltin);
+               inst->prinst->extensionbuiltin = eb;
+       }
+*/
+       if (inst->prinst->field)
+               f(inst->prinst->field);
+       if (inst->prinst->shares)
+               f(inst->prinst->shares);        //free memory
+       f(inst->prinst);
+       f(inst);
+}
+
+void RegisterBuiltin(progfuncs_t *progfuncs, char *name, builtin_t func)
+{
+/*
+       extensionbuiltin_t *eb;
+       eb = memalloc(sizeof(extensionbuiltin_t));
+       eb->prev = progfuncs->prinst->extensionbuiltin;
+       progfuncs->prinst->extensionbuiltin = eb;
+       eb->name = name;
+       eb->func = func;
+*/
+}
+
+#ifndef WIN32
+#define QCLIBINT       //don't use dllspecifications
+#endif
+
+#if defined(QCLIBDLL_EXPORTS)
+__declspec(dllexport)
+#endif
+progfuncs_t * InitProgs(progexterns_t *ext)
+{      
+       progfuncs_t *funcs;
+
+       if (!ext)
+               ext = &defexterns;
+       else
+       {
+               int i;
+               if (ext->progsversion > PROGSTRUCT_VERSION)
+                       return NULL;
+
+               for (i=0;i<sizeof(progexterns_t); i+=4) //make sure there are no items left out.
+                       if (!*(int *)((char *)ext+i))
+                               *(int *)((char *)ext+i) = *(int *)((char *)&defexterns+i);              
+       }       
+#undef memalloc
+#undef pr_trace
+       funcs = ext->memalloc(sizeof(progfuncs_t));     
+       memcpy(funcs, &deffuncs, sizeof(progfuncs_t));
+
+       funcs->prinst = ext->memalloc(sizeof(prinst_t));
+       memset(funcs->prinst,0, sizeof(prinst_t));
+
+       funcs->pr_trace = &funcs->prinst->pr_trace;
+       funcs->progstate = &funcs->pr_progstate;
+       funcs->callargc = &funcs->pr_argc;
+
+       funcs->parms = ext;
+
+       SetEndian();
+       
+       return funcs;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifdef QCC
+void main (int argc, char **argv)
+{
+       progexterns_t ext;
+
+       progfuncs_t *funcs;
+       funcs = InitProgs(&ext);
+       if (funcs->PR_StartCompile(argc, argv))
+               while(funcs->PR_ContinueCompile());
+}
+#endif
diff --git a/misc/mediasource/extra/fteqcc-src/pr_comp.h b/misc/mediasource/extra/fteqcc-src/pr_comp.h
new file mode 100644 (file)
index 0000000..13b93bc
--- /dev/null
@@ -0,0 +1,540 @@
+// this file is shared by the execution and compiler
+
+/*i'm part way through making this work
+I've given up now that I can't work out a way to load pointers.
+Setting them should be fine.
+*/
+#ifndef __PR_COMP_H__
+#define __PR_COMP_H__
+
+
+/*this distinction is made as the execution uses c pointers while compiler uses pointers from the start of the string table of the current progs*/
+#ifdef COMPILER
+typedef int QCC_string_t;
+#else
+//typedef char *string_t;
+#endif
+
+//typedef enum {ev_void, ev_string, ev_float, ev_vector, ev_entity, ev_field, ev_function, ev_pointer, ev_integer, ev_struct, ev_union} etype_t;
+//                             0                       1               2                       3                       4               5                       6                               7                       8               9                       10
+
+#define        OFS_NULL                0
+#define        OFS_RETURN              1
+#define        OFS_PARM0               4               // leave 3 ofs for each parm to hold vectors
+#define        OFS_PARM1               7
+#define        OFS_PARM2               10
+#define        OFS_PARM3               13
+#define        OFS_PARM4               16
+#define        OFS_PARM5               19
+#define        OFS_PARM6               22
+#define        OFS_PARM7               25
+#define        RESERVED_OFS    28
+
+
+enum {
+       OP_DONE,        //0
+       OP_MUL_F,
+       OP_MUL_V,
+       OP_MUL_FV,
+       OP_MUL_VF,
+       OP_DIV_F,
+       OP_ADD_F,
+       OP_ADD_V,
+       OP_SUB_F,
+       OP_SUB_V,
+       
+       OP_EQ_F,        //10
+       OP_EQ_V,
+       OP_EQ_S,
+       OP_EQ_E,
+       OP_EQ_FNC,
+       
+       OP_NE_F,
+       OP_NE_V,
+       OP_NE_S,
+       OP_NE_E,
+       OP_NE_FNC,
+       
+       OP_LE,  //20
+       OP_GE,
+       OP_LT,
+       OP_GT,
+
+       OP_LOAD_F,
+       OP_LOAD_V,
+       OP_LOAD_S,
+       OP_LOAD_ENT,
+       OP_LOAD_FLD,
+       OP_LOAD_FNC,
+
+       OP_ADDRESS,     //30
+
+       OP_STORE_F,
+       OP_STORE_V,
+       OP_STORE_S,
+       OP_STORE_ENT,
+       OP_STORE_FLD,
+       OP_STORE_FNC,
+
+       OP_STOREP_F,
+       OP_STOREP_V,
+       OP_STOREP_S,
+       OP_STOREP_ENT,  //40
+       OP_STOREP_FLD,
+       OP_STOREP_FNC,
+
+       OP_RETURN,
+       OP_NOT_F,
+       OP_NOT_V,
+       OP_NOT_S,
+       OP_NOT_ENT,
+       OP_NOT_FNC,
+       OP_IF,
+       OP_IFNOT,               //50
+       OP_CALL0,               //careful... hexen2 and q1 have different calling conventions
+       OP_CALL1,               //remap hexen2 calls to OP_CALL2H
+       OP_CALL2,
+       OP_CALL3,
+       OP_CALL4,
+       OP_CALL5,
+       OP_CALL6,
+       OP_CALL7,
+       OP_CALL8,
+       OP_STATE,               //60
+       OP_GOTO,
+       OP_AND,
+       OP_OR,
+       
+       OP_BITAND,
+       OP_BITOR,
+
+       
+       //these following ones are Hexen 2 constants.
+       
+       OP_MULSTORE_F,
+       OP_MULSTORE_V,
+       OP_MULSTOREP_F,
+       OP_MULSTOREP_V,
+
+       OP_DIVSTORE_F,  //70
+       OP_DIVSTOREP_F,
+
+       OP_ADDSTORE_F,
+       OP_ADDSTORE_V,
+       OP_ADDSTOREP_F,
+       OP_ADDSTOREP_V,
+
+       OP_SUBSTORE_F,
+       OP_SUBSTORE_V,
+       OP_SUBSTOREP_F,
+       OP_SUBSTOREP_V,
+
+       OP_FETCH_GBL_F, //80
+       OP_FETCH_GBL_V,
+       OP_FETCH_GBL_S,
+       OP_FETCH_GBL_E,
+       OP_FETCH_GBL_FNC,
+
+       OP_CSTATE,
+       OP_CWSTATE,
+
+       OP_THINKTIME,
+
+       OP_BITSET,
+       OP_BITSETP,
+       OP_BITCLR,              //90
+       OP_BITCLRP,
+
+       OP_RAND0,
+       OP_RAND1,
+       OP_RAND2,
+       OP_RANDV0,
+       OP_RANDV1,
+       OP_RANDV2,
+
+       OP_SWITCH_F,
+       OP_SWITCH_V,
+       OP_SWITCH_S,    //100
+       OP_SWITCH_E,
+       OP_SWITCH_FNC,
+
+       OP_CASE,
+       OP_CASERANGE,
+
+
+
+
+
+       //the rest are added
+       //mostly they are various different ways of adding two vars with conversions.
+
+       OP_CALL1H,
+       OP_CALL2H,
+       OP_CALL3H,
+       OP_CALL4H,
+       OP_CALL5H,
+       OP_CALL6H,              //110
+       OP_CALL7H,
+       OP_CALL8H,
+
+
+       OP_STORE_I,
+       OP_STORE_IF,
+       OP_STORE_FI,
+       
+       OP_ADD_I,
+       OP_ADD_FI,
+       OP_ADD_IF,              //110
+  
+       OP_SUB_I,
+       OP_SUB_FI,
+       OP_SUB_IF,
+
+       OP_CONV_ITOF,
+       OP_CONV_FTOI,
+       OP_CP_ITOF,
+       OP_CP_FTOI,
+       OP_LOAD_I,
+       OP_STOREP_I,
+       OP_STOREP_IF,   //120
+       OP_STOREP_FI,
+
+       OP_BITAND_I,
+       OP_BITOR_I,
+
+       OP_MUL_I,
+       OP_DIV_I,
+       OP_EQ_I,
+       OP_NE_I,
+
+       OP_IFNOT_S,
+       OP_IF_S,
+
+       OP_NOT_I,               //130
+
+       OP_DIV_VF,
+
+       OP_XOR_I,
+       OP_RSHIFT_I,
+       OP_LSHIFT_I,
+
+       OP_GLOBALADDRESS,
+       OP_POINTER_ADD, //32 bit pointers
+
+       OP_LOADA_F,
+       OP_LOADA_V,     
+       OP_LOADA_S,
+       OP_LOADA_ENT,   //140
+       OP_LOADA_FLD,           
+       OP_LOADA_FNC,
+       OP_LOADA_I,
+
+       OP_STORE_P,     //152... erm.. wait...
+       OP_LOAD_P,
+
+       OP_LOADP_F,
+       OP_LOADP_V,     
+       OP_LOADP_S,
+       OP_LOADP_ENT,
+       OP_LOADP_FLD,   //150
+       OP_LOADP_FNC,
+       OP_LOADP_I,
+
+       OP_LE_I,
+       OP_GE_I,
+       OP_LT_I,
+       OP_GT_I,
+
+       OP_LE_IF,
+       OP_GE_IF,
+       OP_LT_IF,
+       OP_GT_IF,               //160
+
+       OP_LE_FI,
+       OP_GE_FI,
+       OP_LT_FI,
+       OP_GT_FI,
+
+       OP_EQ_IF,
+       OP_EQ_FI,
+
+       //-------------------------------------
+       //string manipulation.
+       OP_ADD_SF,      //(char*)c = (char*)a + (float)b
+       OP_SUB_S,       //(float)c = (char*)a - (char*)b
+       OP_STOREP_C,//(float)c = *(char*)b = (float)a
+       OP_LOADP_C,     //(float)c = *(char*)                                   //170
+       //-------------------------------------
+
+
+       OP_MUL_IF,
+       OP_MUL_FI,
+       OP_MUL_VI,
+       OP_MUL_IV,
+       OP_DIV_IF,
+       OP_DIV_FI,
+       OP_BITAND_IF,
+       OP_BITOR_IF,
+       OP_BITAND_FI,
+       OP_BITOR_FI,            //180
+       OP_AND_I,
+       OP_OR_I,
+       OP_AND_IF,
+       OP_OR_IF,
+       OP_AND_FI,
+       OP_OR_FI,
+       OP_NE_IF,
+       OP_NE_FI,
+
+//erm... FTEQCC doesn't make use of these... These are for DP.
+       OP_GSTOREP_I,
+       OP_GSTOREP_F,           //190
+       OP_GSTOREP_ENT,
+       OP_GSTOREP_FLD,         // integers
+       OP_GSTOREP_S,
+       OP_GSTOREP_FNC,         // pointers
+       OP_GSTOREP_V,
+       OP_GADDRESS,
+       OP_GLOAD_I,
+       OP_GLOAD_F,
+       OP_GLOAD_FLD,
+       OP_GLOAD_ENT,           //200
+       OP_GLOAD_S,
+       OP_GLOAD_FNC,
+       OP_BOUNDCHECK,
+
+//back to ones that we do use.
+       OP_STOREP_P,
+       OP_PUSH,        //push 4octets onto the local-stack (which is ALWAYS poped on function return). Returns a pointer.
+       OP_POP,         //pop those ones that were pushed (don't over do it). Needs assembler.
+
+       OP_SWITCH_I,//hmm.
+       OP_GLOAD_V,
+
+       OP_IF_F,
+       OP_IFNOT_F,
+
+       OP_NUMREALOPS,
+
+       /*
+       These ops are emulated out, always, and are only present in the compiler.
+       */
+
+       OP_BITSET_I,
+       OP_BITSETP_I,
+
+       OP_MULSTORE_I,
+       OP_DIVSTORE_I,
+       OP_ADDSTORE_I,
+       OP_SUBSTORE_I,
+       OP_MULSTOREP_I,
+       OP_DIVSTOREP_I,
+       OP_ADDSTOREP_I,
+       OP_SUBSTOREP_I,
+
+       OP_MULSTORE_IF,
+       OP_MULSTOREP_IF,
+       OP_DIVSTORE_IF,
+       OP_DIVSTOREP_IF,
+       OP_ADDSTORE_IF,
+       OP_ADDSTOREP_IF,
+       OP_SUBSTORE_IF,
+       OP_SUBSTOREP_IF,
+
+       OP_MULSTORE_FI,
+       OP_MULSTOREP_FI,
+       OP_DIVSTORE_FI,
+       OP_DIVSTOREP_FI,
+       OP_ADDSTORE_FI,
+       OP_ADDSTOREP_FI,
+       OP_SUBSTORE_FI,
+       OP_SUBSTOREP_FI,
+
+       OP_NUMOPS
+};
+
+
+#ifndef COMPILER
+typedef struct statement16_s
+{
+       unsigned short  op;
+       unsigned short  a,b,c;
+} dstatement16_t;
+typedef struct statement32_s
+{
+       unsigned int    op;
+       unsigned int    a,b,c;
+} dstatement32_t;
+#else
+typedef struct QCC_statement16_s
+{
+       unsigned short  op;
+       unsigned short  a,b,c;
+} QCC_dstatement16_t;
+typedef struct QCC_statement32_s
+{
+       unsigned int    op;
+       unsigned int    a,b,c;
+} QCC_dstatement32_t;
+#define QCC_dstatement_t QCC_dstatement32_t
+#endif
+
+//these should be the same except the string type
+#ifndef COMPILER
+typedef struct ddef16_s
+{
+       unsigned short  type;           // if DEF_SAVEGLOBAL bit is set
+                                                               // the variable needs to be saved in savegames
+       unsigned short  ofs;
+       string_t                s_name;
+} ddef16_t;
+
+typedef struct ddef32_s
+{
+       unsigned int    type;           // if DEF_SAVEGLOBAL bit is set
+                                                               // the variable needs to be saved in savegames
+       unsigned int    ofs;
+       string_t                s_name;
+} ddef32_t;
+
+typedef struct fdef_s
+{
+       unsigned int    type;           // if DEF_SAVEGLOBAL bit is set
+                                                               // the variable needs to be saved in savegames
+       unsigned int    ofs;
+       unsigned int    progsofs;       //used at loading time, so maching field offsets (unions/members) are positioned at the same runtime offset.
+       char *          name;
+} fdef_t;
+
+typedef void *ddefXX_t;
+#else
+typedef struct QCC_ddef16_s
+{
+       unsigned short  type;           // if DEF_SAVEGLOBAL bit is set
+                                                               // the variable needs to be saved in savegames
+       unsigned short  ofs;
+       QCC_string_t            s_name;
+} QCC_ddef16_t;
+
+typedef struct QCC_ddef32_s
+{
+       unsigned int    type;           // if DEF_SAVEGLOBAL bit is set
+                                                               // the variable needs to be saved in savegames
+       unsigned int    ofs;
+       QCC_string_t            s_name;
+} QCC_ddef32_t;
+
+#define QCC_ddef_t QCC_ddef32_t
+#endif
+
+#define        DEF_SAVEGLOBAL          (1<<15)
+#define        DEF_SHARED              (1<<14)
+
+#define        MAX_PARMS       8
+
+#ifndef COMPILER
+typedef struct
+{
+       int             first_statement;        // negative numbers are builtins
+       int             parm_start;
+       int             locals;                         // total ints of parms + locals
+       
+       int             profile;                // runtime
+       
+       string_t        s_name;
+       string_t        s_file;                 // source file defined in
+       
+       int             numparms;
+       qbyte   parm_size[MAX_PARMS];
+} dfunction_t;
+#else
+typedef struct
+{
+       unsigned int            first_statement;        // negative numbers are builtins
+       unsigned int            parm_start;
+       int             locals;                         // total ints of parms + locals
+       
+       int             profile;                // runtime
+       
+       QCC_string_t    s_name;
+       QCC_string_t    s_file;                 // source file defined in
+       
+       int             numparms;
+       qbyte   parm_size[MAX_PARMS];
+} QCC_dfunction_t;
+#endif
+
+
+#define        PROG_VERSION    6
+#define PROG_KKQWSVVERSION 7
+#define        PROG_EXTENDEDVERSION    7
+#define PROG_SECONDARYVERSION16 (*(int*)"1FTE" ^ *(int*)"PROG")        //something unlikly and still meaningful (to me)
+#define PROG_SECONDARYVERSION32 (*(int*)"1FTE" ^ *(int*)"32B ")        //something unlikly and still meaningful (to me)
+typedef struct
+{
+       int             version;
+       int             crc;                    // check of header file
+       
+       unsigned int            ofs_statements; //comp 1
+       unsigned int            numstatements;  // statement 0 is an error
+
+       unsigned int            ofs_globaldefs; //comp 2
+       unsigned int            numglobaldefs;
+       
+       unsigned int            ofs_fielddefs;  //comp 4
+       unsigned int            numfielddefs;
+       
+       unsigned int            ofs_functions;  //comp 8
+       unsigned int            numfunctions;   // function 0 is an empty
+       
+       unsigned int            ofs_strings;    //comp 16
+       unsigned int            numstrings;             // first string is a null string
+
+       unsigned int            ofs_globals;    //comp 32
+       unsigned int            numglobals;
+       
+       unsigned int            entityfields;
+
+       //debug / version 7 extensions
+       unsigned int            ofsfiles;       //non list format. no comp
+       unsigned int            ofslinenums;    //numstatements big     //comp 64
+       unsigned int            ofsbodylessfuncs;       //no comp
+       unsigned int            numbodylessfuncs;
+
+       unsigned int    ofs_types;      //comp 128
+       unsigned int    numtypes;
+       unsigned int    blockscompressed;
+
+       int     secondaryversion;       //Constant - to say that any version 7 progs are actually ours, not someone else's alterations.
+} dprograms_t;
+#define standard_dprograms_t_size ((int)&((dprograms_t*)NULL)->ofsfiles)
+
+#endif
+
+
+
+
+
+typedef struct {
+       char filename[128];
+       int size;
+       int compsize;
+       int compmethod;
+       int ofs;
+} includeddatafile_t;
+
+
+
+
+typedef struct typeinfo_s
+{
+       etype_t type;
+
+       int             next;
+       int             aux_type;
+       int             num_parms;
+
+       int             ofs;    //inside a structure.
+       int             size;
+       char    *name;
+} typeinfo_t;
diff --git a/misc/mediasource/extra/fteqcc-src/pr_edict.c b/misc/mediasource/extra/fteqcc-src/pr_edict.c
new file mode 100644 (file)
index 0000000..d6c2119
--- /dev/null
@@ -0,0 +1,3118 @@
+
+
+#define PROGSUSED
+struct edict_s;
+#include "progsint.h"
+//#include "crc.h"
+
+/*int maxedicts;
+
+evalc_t spawnflagscache;
+*/
+
+#ifdef _WIN32
+//this is windows  all files are written with this endian standard. we do this to try to get a little more speed.
+#define NOENDIAN
+#endif
+
+
+vec3_t vec3_origin;
+
+//edictrun_t *sv_edicts;
+//int sv_num_edicts;
+
+//int                          pr_edict_size;  // in bytes
+//int                          pr_max_edict_size;
+
+//unsigned short               pr_crc;
+
+fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs);
+pbool  ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int bits);
+
+
+
+/*
+#define        MAX_FIELD_LEN   64
+#define GEFV_CACHESIZE 5
+
+typedef struct {
+       ddef_t  *pcache;
+       char    field[MAX_FIELD_LEN];
+} gefv_cache;
+
+static gefv_cache      gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
+*/
+
+/*
+=================
+QC_ClearEdict
+
+Sets everything to NULL
+=================
+*/
+void QC_ClearEdict (progfuncs_t *progfuncs, struct edict_s *ed)
+{
+       edictrun_t *e = (edictrun_t *)ed;
+       int num = e->entnum;
+       memset (e->fields, 0, fields_size);
+       e->isfree = false;
+       e->entnum = num;
+}
+
+edictrun_t *ED_AllocIntoTable (progfuncs_t *progfuncs, int num)
+{
+       edictrun_t *e;
+
+       prinst->edicttable[num] = *(struct edict_s **)&e = (void*)memalloc(externs->edictsize);
+       memset(e, 0, externs->edictsize);
+       e->fields = PRAddressableAlloc(progfuncs, fields_size);
+       e->entnum = num;
+       QC_ClearEdict(progfuncs, (struct edict_s*)e);
+
+       return e;
+}
+
+/*
+=================
+ED_Alloc
+
+Either finds a free edict, or allocates a new one.
+Try to avoid reusing an entity that was recently freed, because it
+can cause the client to think the entity morphed into something else
+instead of being removed and recreated, which can cause interpolated
+angles and bad trails.
+=================
+*/
+struct edict_s *ED_Alloc (progfuncs_t *progfuncs)
+{
+       unsigned int                    i;
+       edictrun_t              *e;
+
+       for ( i=0 ; i<sv_num_edicts ; i++)
+       {
+               e = (edictrun_t*)EDICT_NUM(progfuncs, i);
+               // the first couple seconds of server time can involve a lot of
+               // freeing and allocating, so relax the replacement policy
+               if (!e || (e->isfree && ( e->freetime < 2 || *externs->gametime - e->freetime > 0.5 ) ))
+               {
+                       if (!e)
+                               e = ED_AllocIntoTable(progfuncs, i);
+                       else
+                               QC_ClearEdict (progfuncs, (struct edict_s*)e);
+
+                       if (externs->entspawn)
+                               externs->entspawn((struct edict_s *) e, false);
+                       return (struct edict_s *)e;
+               }
+       }
+
+       if (i >= maxedicts-1)   //try again, but use timed out ents.
+       {
+               for ( i=0 ; i<sv_num_edicts ; i++)
+               {
+                       e = (edictrun_t*)EDICT_NUM(progfuncs, i);
+                       // the first couple seconds of server time can involve a lot of
+                       // freeing and allocating, so relax the replacement policy
+                       if (!e || (e->isfree))
+                       {
+                               if (!e)
+                                       e = ED_AllocIntoTable(progfuncs, i);
+                               else
+                                       QC_ClearEdict (progfuncs, (struct edict_s*)e);
+
+                               if (externs->entspawn)
+                                       externs->entspawn((struct edict_s *) e, false);
+                               return (struct edict_s *)e;
+                       }
+               }
+
+               if (i >= maxedicts-2)
+               {
+                       printf("Running out of edicts\n");
+                       pr_trace = 1;   //trip the debugger whilst it's still valid
+               }
+               if (i >= maxedicts-1)
+               {
+                       int size;
+                       char *buf;
+                       buf = progfuncs->save_ents(progfuncs, NULL, &size, 0);
+                       progfuncs->parms->WriteFile("edalloc.dump", buf, size);
+                       Sys_Error ("ED_Alloc: no free edicts");
+               }
+       }
+
+       sv_num_edicts++;
+       e = (edictrun_t*)EDICT_NUM(progfuncs, i);
+
+       if (!e)
+               e = ED_AllocIntoTable(progfuncs, i);
+       else
+               QC_ClearEdict (progfuncs, (struct edict_s*)e);
+
+       if (externs->entspawn)
+               externs->entspawn((struct edict_s *) e, false);
+
+       return (struct edict_s *)e;
+}
+
+/*
+=================
+ED_Free
+
+Marks the edict as free
+FIXME: walk all entities and NULL out references to this entity
+=================
+*/
+void ED_Free (progfuncs_t *progfuncs, struct edict_s *ed)
+{
+       edictrun_t *e = (edictrun_t *)ed;
+//     SV_UnlinkEdict (ed);            // unlink from world bsp
+
+       if (e->isfree)  //this happens on start.bsp where an onlyregistered trigger killtargets itself (when all of this sort die after 1 trigger anyway).
+       {
+               if (pr_depth)
+                       printf("Tried to free free entity within %s\n", pr_xfunction->s_name+progfuncs->stringtable);
+               else
+                       printf("Engine tried to free free entity\n");
+//             if (developer.value == 1)
+//                     pr_trace = true;
+               return;
+       }
+
+       if (externs->entcanfree)
+               if (!externs->entcanfree(ed))   //can stop an ent from being freed.
+                       return;
+
+       e->isfree = true;
+       e->freetime = (float)*externs->gametime;
+
+/*
+       ed->v.model = 0;
+       ed->v.takedamage = 0;
+       ed->v.modelindex = 0;
+       ed->v.colormap = 0;
+       ed->v.skin = 0;
+       ed->v.frame = 0;
+       VectorCopy (vec3_origin, ed->v.origin);
+       VectorCopy (vec3_origin, ed->v.angles);
+       ed->v.nextthink = -1;
+       ed->v.solid = 0;
+*/
+}
+
+//===========================================================================
+
+/*
+============
+ED_GlobalAtOfs
+============
+*/
+ddef16_t *ED_GlobalAtOfs16 (progfuncs_t *progfuncs, int ofs)
+{
+       ddef16_t                *def;
+       unsigned int                    i;
+
+       for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+       {
+               def = &pr_globaldefs16[i];
+               if (def->ofs == ofs)
+                       return def;
+       }
+       return NULL;
+}
+ddef32_t *ED_GlobalAtOfs32 (progfuncs_t *progfuncs, unsigned int ofs)
+{
+       ddef32_t                *def;
+       unsigned int                    i;
+
+       for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+       {
+               def = &pr_globaldefs32[i];
+               if (def->ofs == ofs)
+                       return def;
+       }
+       return NULL;
+}
+
+/*
+============
+ED_FieldAtOfs
+============
+*/
+fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs)
+{
+//     ddef_t          *def;
+       unsigned int                    i;
+
+       for (i=0 ; i<numfields ; i++)
+       {
+               if (field[i].ofs == ofs)
+                       return &field[i];
+       }
+       return NULL;
+}
+/*
+============
+ED_FindField
+============
+*/
+fdef_t *ED_FindField (progfuncs_t *progfuncs, char *name)
+{
+       unsigned int                    i;
+
+       for (i=0 ; i<numfields ; i++)
+       {
+               if (!strcmp(field[i].name, name) )
+                       return &field[i];
+       }
+       return NULL;
+}
+
+
+/*
+============
+ED_FindGlobal
+============
+*/
+ddef16_t *ED_FindGlobal16 (progfuncs_t *progfuncs, char *name)
+{
+       ddef16_t                *def;
+       unsigned int                    i;
+
+       for (i=1 ; i<pr_progs->numglobaldefs ; i++)
+       {
+               def = &pr_globaldefs16[i];
+               if (!strcmp(def->s_name+progfuncs->stringtable,name) )
+                       return def;
+       }
+       return NULL;
+}
+ddef32_t *ED_FindGlobal32 (progfuncs_t *progfuncs, char *name)
+{
+       ddef32_t                *def;
+       unsigned int                    i;
+
+       for (i=1 ; i<pr_progs->numglobaldefs ; i++)
+       {
+               def = &pr_globaldefs32[i];
+               if (!strcmp(def->s_name+progfuncs->stringtable,name) )
+                       return def;
+       }
+       return NULL;
+}
+
+unsigned int ED_FindGlobalOfs (progfuncs_t *progfuncs, char *name)
+{
+       ddef16_t *d16;
+       ddef32_t *d32;
+       switch(current_progstate->intsize)
+       {
+       case 24:
+       case 16:
+               d16 = ED_FindGlobal16(progfuncs, name);
+               return d16?d16->ofs:0;
+       case 32:
+               d32 = ED_FindGlobal32(progfuncs, name);
+               return d32?d32->ofs:0;
+       }
+       Sys_Error("ED_FindGlobalOfs - bad intsize");
+       return 0;
+}
+
+ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum)
+{
+       ddef16_t                *def;
+       unsigned int                    i;
+
+       for (i=1 ; i<pr_progstate[prnum].progs->numglobaldefs ; i++)
+       {
+               def = &pr_progstate[prnum].globaldefs16[i];
+               if (!strcmp(def->s_name+progfuncs->stringtable,name) )
+                       return def;
+       }
+       return NULL;
+}
+ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum)
+{
+       ddef32_t                *def;
+       unsigned int                    i;
+
+       for (i=1 ; i<pr_progstate[prnum].progs->numglobaldefs ; i++)
+       {
+               def = &pr_progstate[prnum].globaldefs32[i];
+               if (!strcmp(def->s_name+progfuncs->stringtable,name) )
+                       return def;
+       }
+       return NULL;
+}
+
+ddef16_t *ED_FindTypeGlobalFromProgs16 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type)
+{
+       ddef16_t                *def;
+       unsigned int                    i;
+
+       for (i=1 ; i<pr_progstate[prnum].progs->numglobaldefs ; i++)
+       {
+               def = &pr_progstate[prnum].globaldefs16[i];
+               if (!strcmp(def->s_name+progfuncs->stringtable,name) )
+               {
+                       if (pr_progstate[prnum].types)
+                       {
+                               if (pr_progstate[prnum].types[def->type&~DEF_SAVEGLOBAL].type != type)
+                                       continue;
+                       }
+                       else if ((def->type&(~DEF_SAVEGLOBAL)) != type)
+                               continue;
+                       return def;
+               }
+       }
+       return NULL;
+}
+
+
+ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type)
+{
+       ddef32_t                *def;
+       unsigned int                    i;
+
+       for (i=1 ; i<pr_progstate[prnum].progs->numglobaldefs ; i++)
+       {
+               def = &pr_progstate[prnum].globaldefs32[i];
+               if (!strcmp(def->s_name+progfuncs->stringtable,name) )
+               {
+                       if (pr_progstate[prnum].types)
+                       {
+                               if (pr_progstate[prnum].types[def->type&~DEF_SAVEGLOBAL].type != type)
+                                       continue;
+                       }
+                       else if ((def->type&(~DEF_SAVEGLOBAL)) != (unsigned)type)
+                               continue;
+                       return def;
+               }
+       }
+       return NULL;
+}
+
+unsigned int *ED_FindGlobalOfsFromProgs (progfuncs_t *progfuncs, char *name, progsnum_t prnum, int type)
+{
+       ddef16_t                *def16;
+       ddef32_t                *def32;
+       static unsigned int pos;
+       switch(pr_progstate[prnum].intsize)
+       {
+       case 16:
+       case 24:
+               def16 = ED_FindTypeGlobalFromProgs16(progfuncs, name, prnum, type);
+               if (!def16)
+                       return NULL;
+               pos = def16->ofs;
+               return &pos;
+       case 32:
+               def32 = ED_FindTypeGlobalFromProgs32(progfuncs, name, prnum, type);
+               if (!def32)
+                       return NULL;
+               return &def32->ofs;
+       }
+       Sys_Error("ED_FindGlobalOfsFromProgs - bad intsize");
+       return 0;
+}
+
+/*
+============
+ED_FindFunction
+============
+*/
+dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, char *name, progsnum_t *prnum, progsnum_t fromprogs)
+{
+       dfunction_t             *func;
+       unsigned int                            i;
+       char *sep;
+
+       progsnum_t pnum;
+
+       if (prnum)
+       {
+               sep = strchr(name, ':');
+               if (sep)
+               {
+                       pnum = atoi(name);
+                       name = sep+1;
+               }
+               else
+               {
+                       if (fromprogs>=0)
+                               pnum = fromprogs;
+                       else
+                               pnum = pr_typecurrent;
+               }
+               *prnum = pnum;
+       }
+       else
+               pnum = pr_typecurrent;
+
+       if ((unsigned)pnum > (unsigned)maxprogs)
+       {
+               printf("Progsnum %i out of bounds\n", pnum);
+               return NULL;
+       }
+
+       if (!pr_progstate[pnum].progs)
+               return NULL;
+
+       for (i=1 ; i<pr_progstate[pnum].progs->numfunctions ; i++)
+       {
+               func = &pr_progstate[pnum].functions[i];
+               if (!strcmp(func->s_name+progfuncs->stringtable,name) )
+                       return func;
+       }
+       return NULL;
+}
+
+/*
+============
+PR_ValueString
+
+Returns a string describing *data in a type specific manner
+=============
+*/
+char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
+{
+       static char     line[256];
+       fdef_t                  *fielddef;
+       dfunction_t     *f;
+
+#ifdef DEF_SAVEGLOBAL
+       type &= ~DEF_SAVEGLOBAL;
+#endif
+
+       if (pr_types)
+               type = pr_types[type].type;
+
+       switch (type)
+       {
+       case ev_struct:
+               sprintf (line, "struct");
+               break;
+       case ev_union:
+               sprintf (line, "union");
+               break;
+       case ev_string:
+               sprintf (line, "%s", PR_StringToNative(progfuncs, val->string));
+               break;
+       case ev_entity:
+               sprintf (line, "entity %i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict)) );
+               break;
+       case ev_function:
+               if (!val->function)
+                       sprintf (line, "NULL function");
+               else
+               {
+                       if ((val->function & 0xff000000)>>24 >= (unsigned)maxprogs || !pr_progstate[(val->function & 0xff000000)>>24].functions)
+                               sprintf (line, "Bad function");
+                       else
+                       {
+                               f = pr_progstate[(val->function & 0xff000000)>>24].functions + (val->function & ~0xff000000);
+                               sprintf (line, "%i:%s()", (val->function & 0xff000000)>>24, f->s_name+progfuncs->stringtable);
+                       }
+               }
+               break;
+       case ev_field:
+               fielddef = ED_FieldAtOfs (progfuncs,  val->_int );
+               if (!fielddef)
+                       sprintf (line, ".??? (%i)", val->_int);
+               else
+                       sprintf (line, ".%s (%i)", fielddef->name, val->_int);
+               break;
+       case ev_void:
+               sprintf (line, "void type");
+               break;
+       case ev_float:
+               sprintf (line, "%5.1f", val->_float);
+               break;
+       case ev_integer:
+               sprintf (line, "%i", val->_int);
+               break;
+       case ev_vector:
+               sprintf (line, "'%5.1f %5.1f %5.1f'", val->_vector[0], val->_vector[1], val->_vector[2]);
+               break;
+       case ev_pointer:
+               sprintf (line, "pointer");
+               {
+//                     int entnum;
+//                     int valofs;
+                       if (val->_int == 0)
+                       {
+                               sprintf (line, "NULL pointer");
+                               break;
+                       }
+               //FIXME: :/
+                       sprintf(line, "UNKNOWN");
+//                     entnum = ((qbyte *)val->edict - (qbyte *)sv_edicts) / pr_edict_size;
+//                     valofs = (int *)val->edict - (int *)edvars(EDICT_NUM(progfuncs, entnum));
+//                     fielddef = ED_FieldAtOfs (progfuncs, valofs );
+//                     if (!fielddef)
+//                             sprintf(line, "ent%i.%s", entnum, "UNKNOWN");
+//                     else
+//                             sprintf(line, "ent%i.%s", entnum, fielddef->s_name);
+               }
+               break;
+       default:
+               sprintf (line, "bad type %i", type);
+               break;
+       }
+
+       return line;
+}
+
+/*
+============
+PR_UglyValueString
+
+Returns a string describing *data in a type specific manner
+Easier to parse than PR_ValueString
+=============
+*/
+char *PR_UglyValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
+{
+       static char     line[256];
+       fdef_t          *fielddef;
+       dfunction_t     *f;
+       int i, j;
+
+#ifdef DEF_SAVEGLOBAL
+       type &= ~DEF_SAVEGLOBAL;
+#endif
+
+       if (pr_types)
+               type = pr_types[type].type;
+
+       switch (type)
+       {
+       case ev_struct:
+               sprintf (line, "structures cannot yet be saved");
+               break;
+       case ev_union:
+               sprintf (line, "unions cannot yet be saved");
+               break;
+       case ev_string:
+               {
+                       char *outs = line;
+                       int outb = sizeof(line)-2;
+                       char *ins = PR_StringToNative(progfuncs, val->string);
+                       //markup the output string.
+                       while(*ins && outb > 0)
+                       {
+                               switch(*ins)
+                               {
+                               case '\n':
+                                       *outs++ = '\\';
+                                       *outs++ = 'n';
+                                       ins++;
+                                       outb-=2;
+                                       break;
+                               case '\"':
+                                       *outs++ = '\\';
+                                       *outs++ = '"';
+                                       ins++;
+                                       outb-=2;
+                                       break;
+                               case '\\':
+                                       *outs++ = '\\';
+                                       *outs++ = '\\';
+                                       ins++;
+                                       outb-=2;
+                                       break;
+                               default:
+                                       *outs++ = *ins++;
+                                       outb--;
+                                       break;
+                               }
+                       }
+                       *outs = 0;
+               }
+               break;
+       case ev_entity:
+               sprintf (line, "%i", val->_int);
+               break;
+       case ev_function:
+               i = (val->function & 0xff000000)>>24;   //progs number
+               if ((unsigned)i >= maxprogs || !pr_progstate[(unsigned)i].progs)
+                       sprintf (line, "BAD FUNCTION INDEX: %i", val->function);
+               else
+               {
+                       j = (val->function & ~0xff000000);      //function number
+                       if ((unsigned)j >= pr_progstate[(unsigned)i].progs->numfunctions)
+                               sprintf(line, "%i:%s", i, "CORRUPT FUNCTION POINTER");
+                       else
+                       {
+                               f = pr_progstate[(unsigned)i].functions + j;
+                               sprintf (line, "%i:%s", i, f->s_name+progfuncs->stringtable);
+                       }
+               }
+               break;
+       case ev_field:
+               fielddef = ED_FieldAtOfs (progfuncs, val->_int );
+               sprintf (line, "%s", fielddef->name);
+               break;
+       case ev_void:
+               sprintf (line, "void");
+               break;
+       case ev_float:
+               if (val->_float == (int)val->_float)
+                       sprintf (line, "%i", (int)val->_float); //an attempt to cut down on the number of .000000 vars..
+               else
+                       sprintf (line, "%f", val->_float);
+               break;
+       case ev_integer:
+               sprintf (line, "%i", val->_int);
+               break;
+       case ev_vector:
+               if (val->_vector[0] == (int)val->_vector[0] && val->_vector[1] == (int)val->_vector[1] && val->_vector[2] == (int)val->_vector[2])
+                       sprintf (line, "%i %i %i", (int)val->_vector[0], (int)val->_vector[1], (int)val->_vector[2]);
+               else
+                       sprintf (line, "%f %f %f", val->_vector[0], val->_vector[1], val->_vector[2]);
+               break;
+       default:
+               sprintf (line, "bad type %i", type);
+               break;
+       }
+
+       return line;
+}
+
+//compatible with Q1 (for savegames)
+char *PR_UglyOldValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
+{
+       static char     line[256];
+       fdef_t          *fielddef;
+       dfunction_t     *f;
+
+#ifdef DEF_SAVEGLOBAL
+       type &= ~DEF_SAVEGLOBAL;
+#endif
+
+       if (pr_types)
+               type = pr_types[type].type;
+
+       switch (type)
+       {
+       case ev_struct:
+               sprintf (line, "structures cannot yet be saved");
+               break;
+       case ev_union:
+               sprintf (line, "unions cannot yet be saved");
+               break;
+       case ev_string:
+               sprintf (line, "%s", PR_StringToNative(progfuncs, val->string));
+               break;
+       case ev_entity:
+               sprintf (line, "%i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict)));
+               break;
+       case ev_function:
+               f = pr_progstate[(val->function & 0xff000000)>>24].functions + (val->function & ~0xff000000);
+               sprintf (line, "%s", f->s_name+progfuncs->stringtable);
+               break;
+       case ev_field:
+               fielddef = ED_FieldAtOfs (progfuncs, val->_int );
+               sprintf (line, "%s", fielddef->name);
+               break;
+       case ev_void:
+               sprintf (line, "void");
+               break;
+       case ev_float:
+               if (val->_float == (int)val->_float)
+                       sprintf (line, "%i", (int)val->_float); //an attempt to cut down on the number of .000000 vars..
+               else
+                       sprintf (line, "%f", val->_float);
+               break;
+       case ev_integer:
+               sprintf (line, "%i", val->_int);
+               break;
+       case ev_vector:
+               if (val->_vector[0] == (int)val->_vector[0] && val->_vector[1] == (int)val->_vector[1] && val->_vector[2] == (int)val->_vector[2])
+                       sprintf (line, "%i %i %i", (int)val->_vector[0], (int)val->_vector[1], (int)val->_vector[2]);
+               else
+                       sprintf (line, "%f %f %f", val->_vector[0], val->_vector[1], val->_vector[2]);
+               break;
+               break;
+       default:
+               sprintf (line, "bad type %i", type);
+               break;
+       }
+
+       return line;
+}
+
+char *PR_TypeString(progfuncs_t *progfuncs, etype_t type)
+{
+#ifdef DEF_SAVEGLOBAL
+       type &= ~DEF_SAVEGLOBAL;
+#endif
+
+       if (pr_types)
+               type = pr_types[type].type;
+
+       switch (type)
+       {
+       case ev_struct:
+               return "struct";
+       case ev_union:
+               return "union";
+       case ev_string:
+               return "string";
+       case ev_entity:
+               return "entity";
+       case ev_function:
+               return "function";
+       case ev_field:
+               return "field";
+       case ev_void:
+               return "void";
+       case ev_float:
+               return "float";
+       case ev_vector:
+               return "vector";
+       case ev_integer:
+               return "integer";
+       default:
+               return "BAD TYPE";
+       }
+}
+
+/*
+============
+PR_GlobalString
+
+Returns a string with a description and the contents of a global,
+padded to 20 field width
+============
+*/
+char *PR_GlobalString (progfuncs_t *progfuncs, int ofs)
+{
+       char    *s;
+       int             i;
+       ddef16_t        *def16;
+       ddef32_t        *def32;
+       void    *val;
+       static char     line[128];
+
+       switch (current_progstate->intsize)
+       {
+       case 16:
+       case 24:
+               val = (void *)&pr_globals[ofs];
+               def16 = ED_GlobalAtOfs16(progfuncs, ofs);
+               if (!def16)
+                       sprintf (line,"%i(?""?""?)", ofs);
+               else
+               {
+                       s = PR_ValueString (progfuncs, def16->type, val);
+                       sprintf (line,"%i(%s)%s", ofs, def16->s_name+progfuncs->stringtable, s);
+               }
+
+               i = strlen(line);
+               for ( ; i<20 ; i++)
+                       strcat (line," ");
+               strcat (line," ");
+               return line;
+       case 32:
+               val = (void *)&pr_globals[ofs];
+               def32 = ED_GlobalAtOfs32(progfuncs, ofs);
+               if (!def32)
+                       sprintf (line,"%i(?""?""?)", ofs);
+               else
+               {
+                       s = PR_ValueString (progfuncs, def32->type, val);
+                       sprintf (line,"%i(%s)%s", ofs, def32->s_name+progfuncs->stringtable, s);
+               }
+
+               i = strlen(line);
+               for ( ; i<20 ; i++)
+                       strcat (line," ");
+               strcat (line," ");
+               return line;
+       }
+       Sys_Error("Bad offset size in PR_GlobalString");
+       return "";
+}
+
+char *PR_GlobalStringNoContents (progfuncs_t *progfuncs, int ofs)
+{
+       int             i;
+       ddef16_t        *def16;
+       ddef32_t        *def32;
+       static char     line[128];
+
+       switch (current_progstate->intsize)
+       {
+       case 16:
+       case 24:
+               def16 = ED_GlobalAtOfs16(progfuncs, ofs);
+               if (!def16)
+                       sprintf (line,"%i(?""?""?)", ofs);
+               else
+                       sprintf (line,"%i(%s)", ofs, def16->s_name+progfuncs->stringtable);
+               break;
+       case 32:
+               def32 = ED_GlobalAtOfs32(progfuncs, ofs);
+               if (!def32)
+                       sprintf (line,"%i(?""?""?)", ofs);
+               else
+                       sprintf (line,"%i(%s)", ofs, def32->s_name+progfuncs->stringtable);
+               break;
+       default:
+               Sys_Error("Bad offset size in PR_GlobalStringNoContents");
+       }
+
+       i = strlen(line);
+       for ( ; i<20 ; i++)
+               strcat (line," ");
+       strcat (line," ");
+
+       return line;
+}
+
+
+/*
+=============
+ED_Print
+
+For debugging
+=============
+*/
+void ED_Print (progfuncs_t *progfuncs, struct edict_s *ed)
+{
+       int             l;
+       fdef_t  *d;
+       int             *v;
+       unsigned int            i;unsigned int j;
+       char    *name;
+       int             type;
+
+       if (((edictrun_t *)ed)->isfree)
+       {
+               printf ("FREE\n");
+               return;
+       }
+
+       printf("\nEDICT %i:\n", NUM_FOR_EDICT(progfuncs, (struct edict_s *)ed));
+       for (i=1 ; i<numfields ; i++)
+       {
+               d = &field[i];
+               name = d->name;
+               l = strlen(name);
+               if (l >= 2 && name[l-2] == '_')
+                       continue;       // skip _x, _y, _z vars
+
+               v = (int *)((char *)edvars(ed) + d->ofs*4);
+
+       // if the value is still all 0, skip the field
+#ifdef DEF_SAVEGLOBAL
+               type = d->type & ~DEF_SAVEGLOBAL;
+#else
+               type = d->type;
+#endif
+
+               for (j=0 ; j<type_size[type] ; j++)
+                       if (v[j])
+                               break;
+               if (j == type_size[type])
+                       continue;
+
+               printf ("%s",name);
+               l = strlen (name);
+               while (l++ < 15)
+                       printf (" ");
+
+               printf ("%s\n", PR_ValueString(progfuncs, d->type, (eval_t *)v));
+       }
+}
+
+void ED_PrintNum (progfuncs_t *progfuncs, int ent)
+{
+       ED_Print (progfuncs, EDICT_NUM(progfuncs, ent));
+}
+
+/*
+=============
+ED_PrintEdicts
+
+For debugging, prints all the entities in the current server
+=============
+*/
+void ED_PrintEdicts (progfuncs_t *progfuncs)
+{
+       unsigned int            i;
+
+       printf ("%i entities\n", sv_num_edicts);
+       for (i=0 ; i<sv_num_edicts ; i++)
+               ED_PrintNum (progfuncs, i);
+}
+
+/*
+=============
+ED_Count
+
+For debugging
+=============
+*/
+void ED_Count (progfuncs_t *progfuncs)
+{
+       unsigned int            i;
+       edictrun_t      *ent;
+       unsigned int            active, models, solid, step;
+
+       active = models = solid = step = 0;
+       for (i=0 ; i<sv_num_edicts ; i++)
+       {
+               ent = (edictrun_t *)EDICT_NUM(progfuncs, i);
+               if (ent->isfree)
+                       continue;
+               active++;
+//             if (ent->v.solid)
+//                     solid++;
+//             if (ent->v.model)
+//                     models++;
+//             if (ent->v.movetype == MOVETYPE_STEP)
+//                     step++;
+       }
+
+       printf ("num_edicts:%3i\n", sv_num_edicts);
+       printf ("active    :%3i\n", active);
+//     Con_Printf ("view      :%3i\n", models);
+//     Con_Printf ("touch     :%3i\n", solid);
+//     Con_Printf ("step      :%3i\n", step);
+
+}
+
+
+
+//============================================================================
+
+
+/*
+=============
+ED_NewString
+=============
+*/
+char *ED_NewString (progfuncs_t *progfuncs, char *string, int minlength)
+{
+       char    *newc, *new_p;
+       int             i,l;
+
+       minlength++;
+
+       l = strlen(string) + 1;
+
+       newc = PRAddressableAlloc (progfuncs, l<minlength?minlength:l);
+       new_p = newc;
+
+       for (i=0 ; i< l ; i++)
+       {
+               if (string[i] == '\\' && i < l-1 && string[i+1] != 0)
+               {
+                       i++;
+                       if (string[i] == 'n')
+                               *new_p++ = '\n';
+                       else
+                               *new_p++ = '\\';
+               }
+               else
+                       *new_p++ = string[i];
+       }
+
+       return newc;
+}
+
+
+/*
+=============
+ED_ParseEval
+
+Can parse either fields or globals
+returns false if error
+=============
+*/
+pbool  ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int bits)
+{
+       int             i;
+       char    string[128];
+       fdef_t  *def;
+       char    *v, *w;
+       void    *d;
+       string_t st;
+       dfunction_t     *func;
+
+       int type;
+
+       switch(bits)
+       {
+       case 16:
+               d = (void *)((int *)base + ((ddef16_t*)key)->ofs);
+
+               if (pr_types)
+                       type = pr_types[((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL].type;
+               else
+                       type = ((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL;
+               break;
+       case 32:
+               d = (void *)((int *)base + ((ddef32_t*)key)->ofs);
+
+               if (pr_types)
+                       type = pr_types[((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL].type;
+               else
+                       type = ((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL;
+               break;
+       default:
+               Sys_Error("Bad bits in ED_ParseEpair");
+               d = 0;
+       }
+
+       switch (type)
+       {
+       case ev_string:
+               st = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, s, 0));
+               *(string_t *)d = st;
+               break;
+
+       case ev_float:
+               *(float *)d = (float)atof (s);
+               break;
+
+       case ev_integer:
+               *(int *)d = atoi (s);
+               break;
+
+       case ev_vector:
+               strcpy (string, s);
+               v = string;
+               w = string;
+               for (i=0 ; i<3 ; i++)
+               {
+                       while (*v && *v != ' ')
+                               v++;
+                       *v = 0;
+                       ((float *)d)[i] = (float)atof (w);
+                       w = v = v+1;
+               }
+               break;
+
+       case ev_entity:
+               *(int *)d = atoi (s);
+               break;
+
+       case ev_field:
+               def = ED_FindField (progfuncs, s);
+               if (!def)
+               {
+                       printf ("Can't find field %s\n", s);
+                       return false;
+               }
+               *(int *)d = def->ofs;
+               break;
+
+       case ev_function:
+               if (s[1]==':'&&s[2]=='\0')
+               {
+                       *(func_t *)d = 0;
+                       return true;
+               }
+               func = ED_FindFunction (progfuncs, s, &i, -1);
+               if (!func)
+               {
+                       printf ("Can't find function %s\n", s);
+                       return false;
+               }
+               *(func_t *)d = (func - pr_progstate[i].functions) | (i<<24);
+               break;
+
+       default:
+               break;
+       }
+       return true;
+}
+
+/*
+====================
+ED_ParseEdict
+
+Parses an edict out of the given string, returning the new position
+ed should be a properly initialized empty edict.
+Used for initial level load and for savegames.
+====================
+*/
+#if 1
+char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent)
+{
+       fdef_t          *key;
+       pbool   init;
+       char            keyname[256];
+       int                     n;
+
+//     eval_t          *val;
+
+       init = false;
+
+// clear it
+//     if (ent != (edictrun_t *)sv_edicts)     // hack
+//             memset (ent+1, 0, pr_edict_size - sizeof(edictrun_t));
+
+// go through all the dictionary pairs
+       while (1)
+       {
+       // parse key
+               data = QCC_COM_Parse (data);
+               if (qcc_token[0] == '}')
+                       break;
+               if (!data)
+               {
+                       printf ("ED_ParseEntity: EOF without closing brace\n");
+                       return NULL;
+               }
+
+               strncpy (keyname, qcc_token, sizeof(keyname)-1);
+               keyname[sizeof(keyname)-1] = 0;
+
+               // another hack to fix heynames with trailing spaces
+               n = strlen(keyname);
+               while (n && keyname[n-1] == ' ')
+               {
+                       keyname[n-1] = 0;
+                       n--;
+               }
+
+       // parse value
+               data = QCC_COM_Parse (data);
+               if (!data)
+               {
+                       printf ("ED_ParseEntity: EOF without closing brace\n");
+                       return NULL; 
+               }
+
+               if (qcc_token[0] == '}')
+               {
+                       printf ("ED_ParseEntity: closing brace without data\n");
+                       return NULL;
+               }
+
+               init = true;
+
+// keynames with a leading underscore are used for utility comments,
+// and are immediately discarded by quake
+               if (keyname[0] == '_')
+                       continue;
+
+               key = ED_FindField (progfuncs, keyname);
+               if (!key)
+               {
+                       if (!strcmp(keyname, "angle"))  //Quake anglehack - we've got to leave it in cos it doesn't work for quake otherwise, and this is a QuakeC lib!
+                       {
+                               if ((key = ED_FindField (progfuncs, "angles")))
+                               {
+                                       sprintf (qcc_token, "0 %f 0", atof(qcc_token)); //change it from yaw to 3d angle
+                                       goto cont;
+                               }
+                       }
+                       if (!strcmp(keyname, "light"))  //Quake lighthack - allows a field name and a classname to go by the same thing in the level editor
+                               if ((key = ED_FindField (progfuncs, "light_lev")))
+                                       goto cont;
+                       printf ("'%s' is not a field\n", keyname);
+                       continue;
+               }
+
+cont:
+               if (!ED_ParseEpair (progfuncs, ent->fields, (ddefXX_t*)key, qcc_token, 32))
+               {
+                       continue;
+//                     Sys_Error ("ED_ParseEdict: parse error on entities");
+               }
+       }
+
+       if (!init)
+               ent->isfree = true;
+
+       return data;
+}
+#endif
+
+/*
+================
+ED_LoadFromFile
+
+The entities are directly placed in the array, rather than allocated with
+ED_Alloc, because otherwise an error loading the map would have entity
+number references out of order.
+
+Creates a server's entity / program execution context by
+parsing textual entity definitions out of an ent file.
+
+Used for both fresh maps and savegame loads.  A fresh map would also need
+to call ED_CallSpawnFunctions () to let the objects initialize themselves.
+================
+*/
+
+char *ED_WriteGlobals(progfuncs_t *progfuncs, char *buffer)    //switch first.
+{
+#define AddS(str) strcpy(buffer, str);buffer+=strlen(str);
+       int             *v;
+       ddef32_t                *def32;
+       ddef16_t                *def16;
+       unsigned int                    i;
+       unsigned int j;
+       char    *name;
+       int                     type;
+       int curprogs = pr_typecurrent;
+       int len;
+       switch(current_progstate->intsize)
+       {
+       case 16:
+       case 24:
+               for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+               {
+                       def16 = &pr_globaldefs16[i];
+                       name = def16->s_name + progfuncs->stringtable;
+                       len = strlen(name);
+                       if (!*name)
+                               continue;
+                       if (name[len-2] == '_' && (name[len-1] == 'x' || name[len-1] == 'y' || name[len-1] == 'z'))
+                               continue;       // skip _x, _y, _z vars (vector components, which are saved as one vector not 3 floats)
+
+                       type = def16->type;
+
+#ifdef DEF_SAVEGLOBAL
+                       if ( !(def16->type & DEF_SAVEGLOBAL) )
+                               continue;
+                       type &= ~DEF_SAVEGLOBAL;
+#endif
+                       if (current_progstate->types)
+                               type = current_progstate->types[type].type;
+                       if (type == ev_function)
+                       {
+                               v = (int *)&current_progstate->globals[def16->ofs];
+                               if ((v[0]&0xff000000)>>24 == (unsigned)curprogs)        //same progs
+                               {
+                                       if (!progfuncs->stringtable[current_progstate->functions[v[0]&0x00ffffff].s_name])
+                                               continue;
+                                       else if (!strcmp(current_progstate->functions[v[0]&0x00ffffff].s_name+ progfuncs->stringtable, name))   //names match. Assume function is at initial value.
+                                               continue;
+                               }
+
+                               if (curprogs!=0)
+                               if ((v[0]&0xff000000)>>24 == 0)
+                                       if (!ED_FindFunction(progfuncs, name, NULL, curprogs))  //defined as extern
+                                       {
+                                               if (!progfuncs->stringtable[pr_progstate[0].functions[v[0]&0x00ffffff].s_name])
+                                                       continue;
+                                               else if (!strcmp(pr_progstate[0].functions[v[0]&0x00ffffff].s_name + progfuncs->stringtable, name))     //same name.
+                                                       continue;
+                                       }
+
+                               //else function has been redirected externally.
+                               goto add16;
+                       }
+                       else if (type != ev_string      //anything other than these is not saved
+                       && type != ev_float
+                       && type != ev_integer
+                       && type != ev_entity
+                       && type != ev_vector)
+                               continue;
+
+                       v = (int *)&current_progstate->globals[def16->ofs];
+
+                       // make sure the value is not null, where there's no point in saving
+                       for (j=0 ; j<type_size[type] ; j++)
+                               if (v[j])
+                                       break;
+                       if (j == type_size[type])
+                               continue;
+
+ add16:
+                       AddS (qcva("\"%s\" ", name));
+                       AddS (qcva("\"%s\"\n", PR_UglyValueString(progfuncs, def16->type&~DEF_SAVEGLOBAL, (eval_t *)v)));
+               }
+               break;
+       case 32:
+               for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+               {
+                       def32 = &pr_globaldefs32[i];
+                       name = def32->s_name + progfuncs->stringtable;
+                       if (name[strlen(name)-2] == '_')
+                               continue;       // skip _x, _y, _z vars (vector components, which are saved as one vector not 3 floats)
+
+                       type = def32->type;
+
+#ifdef DEF_SAVEGLOBAL
+                       if ( !(def32->type & DEF_SAVEGLOBAL) )
+                               continue;
+                       type &= ~DEF_SAVEGLOBAL;
+#endif
+                       if (current_progstate->types)
+                               type = current_progstate->types[type].type;
+                       if (type == ev_function)
+                       {
+                               v = (int *)&current_progstate->globals[def32->ofs];
+                               if ((v[0]&0xff000000)>>24 == (unsigned)curprogs)        //same progs
+                                       if (!strcmp(current_progstate->functions[v[0]&0x00ffffff].s_name+ progfuncs->stringtable, name))        //names match. Assume function is at initial value.
+                                               continue;
+
+                               if (curprogs!=0)
+                               if ((v[0]&0xff000000)>>24 == 0)
+                                       if (!ED_FindFunction(progfuncs, name, NULL, curprogs))  //defined as extern
+                                               if (!strcmp(pr_progstate[0].functions[v[0]&0x00ffffff].s_name+ progfuncs->stringtable, name))   //same name.
+                                                       continue;
+
+                               //else function has been redirected externally.
+                               goto add32;
+                       }
+                       else if (type != ev_string      //anything other than these is not saved
+                       && type != ev_float
+                       && type != ev_integer
+                       && type != ev_entity
+                       && type != ev_vector)
+                               continue;
+
+                       v = (int *)&current_progstate->globals[def32->ofs];
+
+                       // make sure the value is not null, where there's no point in saving
+                       for (j=0 ; j<type_size[type] ; j++)
+                               if (v[j])
+                                       break;
+                       if (j == type_size[type])
+                               continue;
+add32:
+                       AddS (qcva("\"%s\" ", name));
+                       AddS (qcva("\"%s\"\n", PR_UglyValueString(progfuncs, def32->type&~DEF_SAVEGLOBAL, (eval_t *)v)));
+               }
+               break;
+       default:
+               Sys_Error("Bad number of bits in SaveEnts");
+       }
+
+       return buffer;
+}
+
+char *ED_WriteEdict(progfuncs_t *progfuncs, edictrun_t *ed, char *buffer, pbool q1compatible)
+{
+       fdef_t  *d;
+
+       int             *v;
+       unsigned int            i;unsigned int j;
+       char    *name;
+       int             type;
+       int len;
+
+       for (i=0 ; i<numfields ; i++)
+       {
+               d = &field[i];
+               name = d->name;
+               len = strlen(name);
+               if (len>4 && (name[len-2] == '_' && (name[len-1] == 'x' || name[len-1] == 'y' || name[len-1] == 'z')))
+                       continue;       // skip _x, _y, _z vars
+
+               v = (int *)((char*)ed->fields + d->ofs*4);
+
+       // if the value is still all 0, skip the field
+#ifdef DEF_SAVEGLOBAL
+               type = d->type & ~DEF_SAVEGLOBAL;
+#else
+               type = d->type;
+#endif
+
+               for (j=0 ; j<type_size[type] ; j++)
+                       if (v[j])
+                               break;
+               if (j == type_size[type])
+                       continue;
+
+               //add it to the file
+               AddS (qcva("\"%s\" ",name));
+               AddS (qcva("\"%s\"\n", (q1compatible?PR_UglyOldValueString:PR_UglyValueString)(progfuncs, d->type, (eval_t *)v)));
+       }
+
+       return buffer;
+#undef AddS
+}
+
+char *SaveCallStack (progfuncs_t *progfuncs, char *s)
+{
+#define AddS(str) strcpy(s, str);s+=strlen(str);
+       char buffer[8192];
+       dfunction_t     *f;
+       int                     i;
+       int progs;
+
+       int arg;
+       int *globalbase;
+
+       progs = -1;
+
+       if (pr_depth == 0)
+       {
+               AddS ("<NO STACK>\n");
+               return s;
+       }
+
+       globalbase = (int *)pr_globals + pr_xfunction->parm_start + pr_xfunction->locals;
+
+       pr_stack[pr_depth].f = pr_xfunction;
+       for (i=pr_depth ; i>0 ; i--)
+       {
+               f = pr_stack[i].f;
+
+               if (!f)
+               {
+                       AddS ("<NO FUNCTION>\n");
+               }
+               else
+               {
+                       if (pr_stack[i].progsnum != progs)
+                       {
+                               progs = pr_stack[i].progsnum;
+
+                               sprintf(buffer, "//%i %s\n", progs, pr_progstate[progs].filename);
+                               AddS (buffer);
+                       }
+                       if (!f->s_file)
+                               sprintf(buffer, "\t\"%i:%s\"\n", progs, f->s_name+progfuncs->stringtable);
+                       else
+                               sprintf(buffer, "\t\"%i:%s\" //%s\n", progs, f->s_name+progfuncs->stringtable, f->s_file+progfuncs->stringtable);
+                       AddS (buffer);
+
+                       AddS ("\t{\n");
+                       for (arg = 0; arg < f->locals; arg++)
+                       {
+                               ddef16_t *local;
+                               local = ED_GlobalAtOfs16(progfuncs, f->parm_start+arg);
+                               if (!local)
+                                       sprintf(buffer, "\t\tofs%i %i // %f\n", f->parm_start+arg, *(int *)(globalbase - f->locals+arg), *(float *)(globalbase - f->locals+arg) );
+                               else
+                               {
+                                       if (local->type == ev_entity)
+                                       {
+                                               sprintf(buffer, "\t\t\"%s\" \"entity %i\"\n", local->s_name+progfuncs->stringtable, ((eval_t*)(globalbase - f->locals+arg))->edict);
+                                       }
+                                       else
+                                               sprintf(buffer, "\t\t\"%s\"\t\"%s\"\n", local->s_name+progfuncs->stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase - f->locals+arg)));
+
+                                       if (local->type == ev_vector)
+                                               arg+=2;
+                               }
+                               AddS (buffer);
+                       }
+                       AddS ("\t}\n");
+
+                       if (i == pr_depth)
+                               globalbase = localstack + localstack_used - f->locals;
+                       else
+                               globalbase -= f->locals;
+               }
+       }
+       return s;
+#undef AddS
+}
+
+//there are two ways of saving everything.
+//0 is to save just the entities.
+//1 is to save the entites, and all the progs info so that all the variables are saved off, and it can be reloaded to exactly how it was (provided no files or data has been changed outside, like the progs.dat for example)
+char *SaveEnts(progfuncs_t *progfuncs, char *mem, int *len, int alldata)
+{
+#define AddS(str) strcpy(s, str);s+=strlen(str);
+       char *s, *os;
+       unsigned int a;
+       int oldprogs;
+
+       if (mem)
+       {
+               os = s = mem;
+       }
+       else
+               os = s = memalloc(5*1024*1024);
+
+       if (alldata == 2)
+       {       //special Q1 savegame compatability mode.
+               //engine will need to store references to progs type and will need to preload the progs and inti the ents itself before loading.
+
+               //Make sure there is only 1 progs loaded.
+               for (a = 1; a < maxprogs; a++)
+               {
+                       if (pr_progstate[a].progs)
+                               break;
+               }
+               if (!pr_progstate[0].progs || a != maxprogs)    //the state of the progs wasn't Q1 compatible.
+               {
+                       memfree(os);
+                       return NULL;
+               }
+
+               //write the globals
+               AddS ("{\n");
+
+               oldprogs = pr_typecurrent;
+               PR_SwitchProgs(progfuncs, 0);
+
+               s = ED_WriteGlobals(progfuncs, s);
+
+               PR_SwitchProgs(progfuncs, oldprogs);
+
+               AddS ("}\n");
+
+
+               //write the ents
+               for (a = 0; a < sv_num_edicts; a++)
+               {
+                       edictrun_t *ed = (edictrun_t *)EDICT_NUM(progfuncs, a);
+
+                       AddS ("{\n");
+
+                       if (!ed->isfree)
+                               s = ED_WriteEdict(progfuncs, ed, s, true);
+
+                       AddS ("}\n");
+               }
+
+               *len = s - os;
+               return os;
+       }
+
+       if (alldata)
+       {
+               AddS("general {\n");
+               AddS(qcva("\"maxprogs\" \"%i\"\n", maxprogs));
+//             AddS(qcva("\"maxentities\" \"%i\"\n", maxedicts));
+//             AddS(qcva("\"mem\" \"%i\"\n", hunksize));
+//             AddS(qcva("\"crc\" \"%i\"\n", header_crc));
+               AddS(qcva("\"numentities\" \"%i\"\n", sv_num_edicts));
+               AddS("}\n");
+
+               oldprogs = pr_typecurrent;
+
+               for (a = 0; a < maxprogs; a++)
+               {
+                       if (!pr_progstate[a].progs)
+                               continue;
+                       PR_SwitchProgs(progfuncs, a);
+                       {
+                               AddS (qcva("progs %i {\n", a));
+                               AddS (qcva("\"filename\" \"%s\"\n", pr_progstate[a].filename));
+                               AddS (qcva("\"crc\" \"%i\"\n", pr_progs->crc));
+                               AddS (qcva("\"numbuiltins\" \"%i\"\n", current_progstate->numbuiltins));
+                               AddS ("}\n");
+                       }
+               }
+
+               if (alldata == 3)
+               {
+                       //include callstack
+                       AddS("stacktrace {\n");
+                       s = SaveCallStack(progfuncs, s);
+                       AddS("}\n");
+               }
+
+               for (a = 0; a < maxprogs; a++)  //I would mix, but external functions rely on other progs being loaded
+               {
+                       if (!pr_progstate[a].progs)
+                               continue;
+
+                       AddS (qcva("globals %i {\n", a));
+
+                       PR_SwitchProgs(progfuncs, a);
+
+                       s = ED_WriteGlobals(progfuncs, s);
+
+                       AddS ("}\n");
+               }
+               PR_SwitchProgs(progfuncs, oldprogs);
+       }
+       for (a = 0; a < sv_num_edicts; a++)
+       {
+               edictrun_t *ed = (edictrun_t *)EDICT_NUM(progfuncs, a);
+
+               if (ed->isfree)
+                       continue;
+
+               AddS (qcva("entity %i{\n", a));
+
+               s = ED_WriteEdict(progfuncs, ed, s, false);
+
+               AddS ("}\n");
+       }
+
+       *len = s - os;
+       return os;
+
+#undef AddS
+}
+
+int header_crc;
+
+//if 'general' block is found, this is a compleate state, otherwise, we should spawn entities like
+int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
+{
+       eval_t *fulldata;       //this is part of FTE_FULLSPAWNDATA
+       char *datastart;
+
+       eval_t *var;
+
+       char filename[128];
+       int num;
+       int numbuiltins;
+       edictrun_t *ed=NULL;
+       ddef16_t *d16;
+       ddef32_t *d32;
+       func_t CheckSpawn=0;
+
+       extern edictrun_t tempedict;
+
+       int crc = 1;
+       int entsize = 0;
+       int numents = 0;
+
+       pbool resethunk=0;
+       pbool isloadgame;
+       if (!strncmp(file, "loadgame", 8))
+       {
+               isloadgame = true;
+               numents = -1;
+               file+=8;
+               fulldata = NULL;
+       }
+       else
+       {
+               isloadgame = false;
+
+               if (pr_typecurrent>=0)
+                       num = ED_FindGlobalOfs(progfuncs, "__fullspawndata");
+               else
+                       num = 0;
+               if (num)
+                       fulldata = (eval_t *)((int *)pr_globals + num);
+               else
+                       fulldata = NULL;
+       }
+
+       while(1)
+       {
+               datastart = file;
+               file = QCC_COM_Parse(file);
+               if (file == NULL)
+                       break;  //finished reading file
+               else if (!strcmp(qcc_token, "entity"))
+               {
+                       if (entsize == 0 && resethunk)  //edicts have not yet been initialized, and this is a compleate load (memsize has been set)
+                       {
+                               entsize = PR_InitEnts(progfuncs, maxedicts);
+//                             sv_num_edicts = numents;
+
+                               for (num = 0; num < numents; num++)
+                               {
+                                       ed = (edictrun_t *)EDICT_NUM(progfuncs, num);
+
+                                       if (!ed)
+                                       {
+                                               ed = ED_AllocIntoTable(progfuncs, num);
+                                               ed->isfree = true;
+                                               if (externs->entspawn)
+                                                       externs->entspawn((struct edict_s *) ed, true);
+                                       }
+                               }
+                       }
+
+                       file = QCC_COM_Parse(file);
+                       num = atoi(qcc_token);
+                       file = QCC_COM_Parse(file);
+                       if (qcc_token[0] != '{')
+                               Sys_Error("Progs loading found %s, not '{'", qcc_token);
+                       if (!resethunk)
+                               ed = (edictrun_t *)ED_Alloc(progfuncs);
+                       else
+                       {
+                               ed = (edictrun_t *)EDICT_NUM(progfuncs, num);
+
+                               if (!ed)
+                               {
+                                       Sys_Error("Edict was not allocated\n");
+                                       ed = ED_AllocIntoTable(progfuncs, num);
+                               }
+                       }
+                       ed->isfree = false;
+                       if (externs->entspawn)
+                               externs->entspawn((struct edict_s *) ed, true);
+                       file = ED_ParseEdict(progfuncs, file, ed);
+
+                       if (killonspawnflags)
+                       {
+                               var = GetEdictFieldValue (progfuncs, (struct edict_s *)&ed, "spawnflags", &spawnflagscache);
+                               if (var)
+                               {
+                                       if ((int)var->_float & (int)killonspawnflags)
+                                       {
+                                               ed->isfree = true;
+                                               continue;
+                                       }
+                               }
+                       }
+
+                       if (!resethunk)
+                       {
+                               dfunction_t *f;
+                               if ((var = GetEdictFieldValue (progfuncs, (struct edict_s *)ed, "classname", NULL)))
+                               {
+                                       f = ED_FindFunction(progfuncs, var->string + progfuncs->stringtable, NULL, -1);
+                                       if (f)
+                                       {
+                                               var = (eval_t *)((int *)pr_globals + ED_FindGlobalOfs(progfuncs, "self"));
+                                               var->edict = EDICT_TO_PROG(progfuncs, ed);
+                                               PR_ExecuteProgram(progfuncs, f-pr_functions);
+                                       }
+                               }
+                       }
+               }
+               else if (!strcmp(qcc_token, "progs"))
+               {
+                       file = QCC_COM_Parse(file);
+                       num = atoi(qcc_token);
+                       file = QCC_COM_Parse(file);
+                       if (qcc_token[0] != '{')
+                               Sys_Error("Progs loading found %s, not '{'", qcc_token);
+
+
+                       filename[0] = '\0';
+                       header_crc = 0;
+                       numbuiltins = 0;
+
+                       while(1)
+                       {
+                               file = QCC_COM_Parse(file);     //read the key
+                               if (!file)
+                                       Sys_Error("EOF in progs block");
+
+                               if (!strcmp("filename", qcc_token))     //check key get and save values
+                                       {file = QCC_COM_Parse(file); strcpy(filename, qcc_token);}
+                               else if (!strcmp("crc", qcc_token))
+                                       {file = QCC_COM_Parse(file); header_crc = atoi(qcc_token);}
+                               else if (!strcmp("numbuiltins", qcc_token))
+                                       {file = QCC_COM_Parse(file); numbuiltins = atoi(qcc_token);}
+                               else if (qcc_token[0] == '}')   //end of block
+                                       break;
+                               else
+                                       Sys_Error("Bad key \"%s\" in progs block", qcc_token);
+                       }
+
+                       PR_ReallyLoadProgs(progfuncs, filename, header_crc, &pr_progstate[num], true);
+                       if (!externs->builtinsfor)
+                       {
+                       //      Sys_Error("Couldn't reset the builtin functions");
+                               current_progstate->builtins = NULL;     //these are specific, we assume the global ones were set via pr_configure
+                               current_progstate->numbuiltins = 0;
+                       }
+                       else
+                       {
+                               current_progstate->builtins = externs->builtinsfor(num, header_crc);
+                               current_progstate->numbuiltins = numbuiltins;
+                       }
+               }
+               else if (!strcmp(qcc_token, "globals"))
+               {
+                       if (entsize == 0 && resethunk)  //by the time we parse some globals, we MUST have loaded all progs
+                       {
+                               entsize = PR_InitEnts(progfuncs, maxedicts);
+//                             sv_num_edicts = numents;
+
+                               for (num = 0; num < numents; num++)
+                               {
+                                       ed = (edictrun_t *)EDICT_NUM(progfuncs, num);
+
+                                       if (!ed)
+                                       {
+                                               ed = ED_AllocIntoTable(progfuncs, num);
+                                               ed->isfree = true;
+                                       }
+
+                                       if (externs->entspawn)
+                                               externs->entspawn((struct edict_s *) ed, true);
+                               }
+                       }
+
+                       file = QCC_COM_Parse(file);
+                       num = atoi(qcc_token);
+
+                       file = QCC_COM_Parse(file);
+                       if (qcc_token[0] != '{')
+                               Sys_Error("Globals loading found \'%s\', not '{'", qcc_token);
+
+                       PR_SwitchProgs(progfuncs, num);
+                       while (1)
+                       {
+                               file = QCC_COM_Parse(file);
+                               if (qcc_token[0] == '}')
+                                       break;
+                               else if (!qcc_token[0] || !file)
+                                       Sys_Error("EOF when parsing global values");
+
+                               switch(current_progstate->intsize)
+                               {
+                               case 16:
+                               case 24:
+                                       if (!(d16 = ED_FindGlobal16(progfuncs, qcc_token)))
+                                       {
+                                               file = QCC_COM_Parse(file);
+                                               printf("global value %s not found", qcc_token);
+                                       }
+                                       else
+                                       {
+                                               file = QCC_COM_Parse(file);
+                                               ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, 16);
+                                       }
+                                       break;
+                               case 32:
+                                       if (!(d32 = ED_FindGlobal32(progfuncs, qcc_token)))
+                                       {
+                                               file = QCC_COM_Parse(file);
+                                               printf("global value %s not found", qcc_token);
+                                       }
+                                       else
+                                       {
+                                               file = QCC_COM_Parse(file);
+                                               ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, 32);
+                                       }
+                                       break;
+                               default:
+                                       Sys_Error("Bad intsize in LoadEnts");
+                               }
+                       }
+
+//                     file = QCC_COM_Parse(file);
+//                     if (com_token[0] != '}')
+//                             Sys_Error("Progs loading found %s, not '}'", qcc_token);
+               }
+               else if (!strcmp(qcc_token, "general"))
+               {
+                       QC_StartShares(progfuncs);
+//                     QC_InitShares();        //forget stuff
+//                     pr_edict_size = 0;
+                       max_fields_size=0;
+
+                       file = QCC_COM_Parse(file);
+                       if (qcc_token[0] != '{')
+                               Sys_Error("Progs loading found %s, not '{'", qcc_token);
+
+                       while(1)
+                       {
+                               file = QCC_COM_Parse(file);     //read the key
+                               if (!file)
+                                       Sys_Error("EOF in general block");
+
+                               if (!strcmp("maxprogs", qcc_token))     //check key get and save values
+                                       {file = QCC_COM_Parse(file); maxprogs = atoi(qcc_token);}
+//                             else if (!strcmp("maxentities", com_token))
+//                                     {file = QCC_COM_Parse(file); maxedicts = atoi(qcc_token);}
+//                             else if (!strcmp("mem", com_token))
+//                                     {file = QCC_COM_Parse(file); memsize = atoi(qcc_token);}
+//                             else if (!strcmp("crc", com_token))
+//                                     {file = QCC_COM_Parse(file); crc = atoi(qcc_token);}
+                               else if (!strcmp("numentities", qcc_token))
+                                       {file = QCC_COM_Parse(file); numents = atoi(qcc_token);}
+                               else if (qcc_token[0] == '}')   //end of block
+                                       break;
+                               else
+                                       Sys_Error("Bad key \"%s\" in general block", qcc_token);
+                       }
+
+                       PRAddressableFlush(progfuncs, -1);
+                       resethunk=true;
+
+                       pr_progstate = PRHunkAlloc(progfuncs, sizeof(progstate_t) * maxprogs);
+                       pr_typecurrent=0;
+
+                       sv_num_edicts = 1;      //set up a safty buffer so things won't go horribly wrong too often
+                       sv_edicts=(struct edict_s *)&tempedict;
+                       prinst->edicttable = &sv_edicts;
+
+
+                       sv_num_edicts = numents;        //should be fine
+
+//                     PR_Configure(crc, NULL, memsize, maxedicts, maxprogs);
+               }
+               else if (!strcmp(qcc_token, "{"))
+               {
+                       if (isloadgame)
+                       {
+                               if (numents == -1)      //globals
+                               {
+                                       while (1)
+                                       {
+                                               file = QCC_COM_Parse(file);
+                                               if (qcc_token[0] == '}')
+                                                       break;
+                                               else if (!qcc_token[0] || !file)
+                                                       Sys_Error("EOF when parsing global values");
+
+                                               switch(current_progstate->intsize)
+                                               {
+                                               case 16:
+                                               case 24:
+                                                       if (!(d16 = ED_FindGlobal16(progfuncs, qcc_token)))
+                                                       {
+                                                               file = QCC_COM_Parse(file);
+                                                               printf("global value %s not found", qcc_token);
+                                                       }
+                                                       else
+                                                       {
+                                                               file = QCC_COM_Parse(file);
+                                                               ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, 16);
+                                                       }
+                                                       break;
+                                               case 32:
+                                                       if (!(d32 = ED_FindGlobal32(progfuncs, qcc_token)))
+                                                       {
+                                                               file = QCC_COM_Parse(file);
+                                                               printf("global value %s not found", qcc_token);
+                                                       }
+                                                       else
+                                                       {
+                                                               file = QCC_COM_Parse(file);
+                                                               ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, 32);
+                                                       }
+                                                       break;
+                                               default:
+                                                       Sys_Error("Bad intsize in LoadEnts");
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       ed = (edictrun_t *)EDICT_NUM(progfuncs, numents);
+                                       if (!ed)
+                                               ed = ED_AllocIntoTable(progfuncs, numents);
+
+                                       if (externs->entspawn)
+                                               externs->entspawn((struct edict_s *) ed, true);
+
+                                       sv_num_edicts = numents;
+                                       ed->isfree = false;
+                                       file = ED_ParseEdict (progfuncs, file, ed);
+                               }
+                               numents++;
+                               continue;
+                       }
+
+                       if (entsize == 0 && resethunk)  //edicts have not yet been initialized, and this is a compleate load (memsize has been set)
+                       {
+                               entsize = PR_InitEnts(progfuncs, maxedicts);
+//                             sv_num_edicts = numents;
+
+                               for (num = 0; num < numents; num++)
+                               {
+                                       ed = (edictrun_t *)EDICT_NUM(progfuncs, num);
+
+                                       if (!ed)
+                                       {
+                                               ed = ED_AllocIntoTable(progfuncs, num);
+                                               ed->isfree = true;
+                                       }
+                               }
+                       }
+
+                       if (!ed)        //first entity
+                               ed = (edictrun_t *)EDICT_NUM(progfuncs, 0);
+                       else
+                               ed = (edictrun_t *)ED_Alloc(progfuncs);
+                       ed->isfree = false;
+                       if (externs->entspawn)
+                               externs->entspawn((struct edict_s *) ed, true);
+                       file = ED_ParseEdict(progfuncs, file, ed);
+
+                       if (killonspawnflags)
+                       {
+                               var = GetEdictFieldValue (progfuncs, (struct edict_s *)ed, "spawnflags", &spawnflagscache);
+                               if (var)
+                               {
+                                       if ((int)var->_float & (int)killonspawnflags)
+                                       {
+                                               ed->isfree = true;
+                                               ed->freetime = 0;
+                                               continue;
+                                       }
+                               }
+                       }
+
+                       if (!resethunk)
+                       {
+                               char *eclassname;
+                               func_t f;
+                               if (!CheckSpawn)
+                                       CheckSpawn = PR_FindFunc(progfuncs, "CheckSpawn", -2);
+
+                               var = GetEdictFieldValue (progfuncs, (struct edict_s *)ed, "classname", NULL);
+                               if (!var || !var->string || !*PR_StringToNative(progfuncs, var->string))
+                               {
+                                       printf("No classname\n");
+                                       ED_Free(progfuncs, (struct edict_s *)ed);
+                               }
+                               else
+                               {
+                                       eval_t *selfvar;
+
+                                       //added by request of Mercury.
+                                       if (fulldata)   //this is a vital part of HL map support!!!
+                                       {       //essentually, it passes the ent's spawn info to the ent.
+                                               char *nl;       //otherwise it sees only the named fields of
+                                               char *spawndata;//a standard quake ent.
+                                               spawndata = PRHunkAlloc(progfuncs, file - datastart +1);
+                                               strncpy(spawndata, datastart, file - datastart);
+                                               spawndata[file - datastart] = '\0';
+                                               for (nl = spawndata; *nl; nl++)
+                                                       if (*nl == '\n')
+                                                               *nl = '\t';
+                                               fulldata->string = PR_StringToProgs(progfuncs, spawndata);
+                                       }
+
+                                       selfvar = (eval_t *)((int *)pr_globals + ED_FindGlobalOfs(progfuncs, "self"));
+                                       selfvar->edict = EDICT_TO_PROG(progfuncs, ed);
+
+                                       //DP_SV_SPAWNFUNC_PREFIX support
+                                       eclassname = PR_StringToNative(progfuncs, var->string);
+#ifdef _WIN32
+                                       _snprintf(filename, sizeof(filename), "spawnfunc_%s", eclassname);
+                                       filename[sizeof(filename)-1] = 0;
+#else
+                                       snprintf(filename, sizeof(filename), "spawnfunc_%s", eclassname);
+#endif
+                                       f = PR_FindFunc(progfuncs, filename, PR_ANYBACK);
+                                       if (!f)
+                                               f = PR_FindFunc(progfuncs, eclassname, PR_ANYBACK);
+                                       if (f)
+                                       {
+                                               if (CheckSpawn)
+                                               {
+                                                       G_INT(OFS_PARM0) = f;
+                                                       PR_ExecuteProgram(progfuncs, CheckSpawn);
+                                                       //call the spawn func or remove.
+                                               }
+                                               else
+                                                       PR_ExecuteProgram(progfuncs, f);
+                                       }
+                                       else if (CheckSpawn)
+                                       {
+                                               G_INT(OFS_PARM0) = 0;
+                                               PR_ExecuteProgram(progfuncs, CheckSpawn);
+                                               //the mod is responsible for freeing unrecognised ents.
+                                       }
+                                       else
+                                       {
+                                               printf("Couldn't find spawn function %s\n", PR_StringToNative(progfuncs, var->string));
+                                               ED_Free(progfuncs, (struct edict_s *)ed);
+                                       }
+                               }
+                       }
+               }
+               else
+                       Sys_Error("Command %s not recognised", qcc_token);
+       }
+       if (resethunk)
+       {
+               header_crc = crc;
+               if (externs->loadcompleate)
+                       externs->loadcompleate(entsize);
+
+               sv_num_edicts = numents;
+       }
+
+       if (resethunk)
+       {
+               return entsize;
+       }
+       else
+               return max_fields_size;
+}
+
+#define AddS(str) strcpy(s, str);s+=strlen(str);
+
+char *SaveEnt (progfuncs_t *progfuncs, char *buf, int *size, struct edict_s *ed)
+{
+       fdef_t  *d;
+       int             *v;
+       unsigned int            i;unsigned int j;
+       char    *name;
+       int             type;
+
+       char *s = buf;
+
+//     if (ed->free)
+//             continue;
+
+       AddS ("{\n");
+
+
+       for (i=0 ; i<numfields ; i++)
+       {
+               int len;
+
+               d = &field[i];
+               name = d->name;
+               len = strlen(name); // should we skip vars with no name?
+               if (len > 2 && name[len-2] == '_')
+                       continue;       // skip _x, _y, _z vars
+
+               v = (int*)((edictrun_t*)ed)->fields + d->ofs;
+
+       // if the value is still all 0, skip the field
+               type = d->type & ~DEF_SAVEGLOBAL;
+               for (j=0 ; j<type_size[type] ; j++)
+                       if (v[j])
+                               break;
+               if (j == type_size[type])
+                       continue;
+
+               //add it to the file
+               AddS (qcva("\"%s\" ",name));
+               AddS (qcva("\"%s\"\n", PR_UglyValueString(progfuncs, d->type, (eval_t *)v)));
+       }
+
+       AddS ("}\n");
+
+       *size = s - buf;
+
+       return buf;
+}
+struct edict_s *RestoreEnt (progfuncs_t *progfuncs, char *buf, int *size, struct edict_s *ed)
+{
+       edictrun_t *ent;
+       char *start = buf;
+
+       buf = QCC_COM_Parse(buf);       //read the key
+       if (!buf || !*qcc_token)
+               return NULL;
+
+       if (strcmp(qcc_token, "{"))
+               Sys_Error("Restore Ent with no opening brace");
+
+       if (!ed)
+               ent = (edictrun_t *)ED_Alloc(progfuncs);
+       else
+               ent = (edictrun_t *)ed;
+       ent->isfree = false;
+
+       if (externs->entspawn)
+               externs->entspawn((struct edict_s *) ent, false);
+
+       buf = ED_ParseEdict(progfuncs, buf, ent);
+
+       *size = buf - start;
+
+       return (struct edict_s *)ent;
+}
+
+#define Host_Error Sys_Error
+
+//return true if pr_progs needs recompiling (source files have changed)
+pbool PR_TestRecompile(progfuncs_t *progfuncs)
+{
+       int newsize;
+       int num, found=0, lost=0, changed=0;
+       includeddatafile_t *s;
+       if (!pr_progs->ofsfiles)
+               return false;
+
+       num = *(int*)((char *)pr_progs + pr_progs->ofsfiles);
+       s = (includeddatafile_t *)((char *)pr_progs + pr_progs->ofsfiles+4);
+       while(num>0)
+       {
+               newsize = externs->FileSize(s->filename);
+               if (newsize == -1)      //ignore now missing files. - the referencer must have changed...
+                       lost++;
+               else if (s->size != newsize)    //file
+                       changed++;
+               else
+                       found++;
+
+               s++;
+               num--;
+       }
+       if (lost > found+changed)
+               return false;
+       if (changed)
+               return true;
+       return false;
+}
+/*
+#ifdef _DEBUG
+//this is for debugging.
+//I'm using this to detect incorrect string types while converting 32bit string pointers with bias to bound indexes.
+void PR_TestForWierdness(progfuncs_t *progfuncs)
+{
+       unsigned int i;
+       int e;
+       edictrun_t *ed;
+       for (i = 0; i < pr_progs->numglobaldefs; i++)
+       {
+               if ((pr_globaldefs16[i].type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_string)
+               {
+                       if (G_INT(pr_globaldefs16[i].ofs) < 0 || G_INT(pr_globaldefs16[i].ofs) >= addressableused)
+                               printf("String type irregularity on \"%s\" \"%s\"\n", pr_globaldefs16[i].s_name+progfuncs->stringtable, G_INT(pr_globaldefs16[i].ofs)+progfuncs->stringtable);
+               }
+       }
+
+       for (i = 0; i < numfields; i++)
+       {
+               if ((field[i].type&~(DEF_SHARED|DEF_SAVEGLOBAL)) == ev_string)
+               {
+                       for (e = 0; e < sv_num_edicts; e++)
+                       {
+                               ed = (edictrun_t*)EDICT_NUM(progfuncs, e);
+                               if (ed->isfree)
+                                       continue;
+                               if (((int *)ed->fields)[field[i].ofs] < 0 || ((int *)ed->fields)[field[i].ofs] >= addressableused)
+                                       printf("String type irregularity \"%s\" \"%s\"\n", field[i].name, ((int *)ed->fields)[field[i].ofs]+progfuncs->stringtable);
+                       }
+               }
+       }
+}
+#endif
+*/
+char *decode(int complen, int len, int method, char *info, char *buffer);
+/*
+===============
+PR_LoadProgs
+===============
+*/
+int PR_ReallyLoadProgs (progfuncs_t *progfuncs, char *filename, int headercrc, progstate_t *progstate, pbool complain)
+{
+       unsigned int            i, type;
+//     extensionbuiltin_t *eb;
+//     float   fl;
+       int len;
+//     int num;
+//     dfunction_t *f, *f2;
+       ddef16_t *d16;
+       ddef32_t *d32;
+       int *d2;
+       eval_t *eval;
+       char *s;
+       int progstype;
+       int trysleft = 2;
+//     bool qfhack = false;
+       pbool isfriked = false; //all imediate values were stripped, which causes problems with strings.
+       pbool hexencalling = false;     //hexen style calling convention. The opcodes themselves are used as part of passing the arguments;
+       ddef16_t *gd16, *fld16;
+       float *glob;
+       dfunction_t *fnc;
+       dstatement16_t *st16;
+
+       int hmark=0xffffffff;
+
+       int reorg = prinst->reorganisefields || numfields;
+
+       int stringadjust;
+
+       current_progstate = progstate;
+
+       strcpy(current_progstate->filename, filename);
+
+
+// flush the non-C variable lookup cache
+//     for (i=0 ; i<GEFV_CACHESIZE ; i++)
+//             gefvCache[i].field[0] = 0;
+
+       memset(&spawnflagscache, 0, sizeof(evalc_t));
+
+       if (externs->autocompile == PR_COMPILEALWAYS)   //always compile before loading
+       {
+               printf("Forcing compile of progs %s\n", filename);
+               if (!CompileFile(progfuncs, filename))
+                       return false;
+       }
+
+//     CRC_Init (&pr_crc);
+
+retry:
+       if ((len=externs->FileSize(filename))<=0)
+       {
+               if (externs->autocompile == PR_COMPILENEXIST || externs->autocompile == PR_COMPILECHANGED)      //compile if file is not found (if 2, we have already tried, so don't bother)
+               {
+                       if (hmark==0xffffffff)  //first try
+                       {
+                               printf("couldn't open progs %s. Attempting to compile.\n", filename);
+                               CompileFile(progfuncs, filename);
+                       }
+                       if ((len=externs->FileSize(filename))<0)
+                       {
+                               printf("Couldn't find or compile file %s\n", filename);
+                               return false;
+                       }
+               }
+               else if (externs->autocompile == PR_COMPILEIGNORE)
+                       return false;
+               else
+               {
+                       printf("Couldn't find file %s\n", filename);
+                       return false;
+               }
+       }
+
+       hmark = PRHunkMark(progfuncs);
+       pr_progs = PRHunkAlloc(progfuncs, len+1);
+       if (!externs->ReadFile(filename, pr_progs, len+1))
+       {
+               if (!complain)
+                       return false;
+               printf("Failed to open %s", filename);
+               return false;
+       }
+
+//     for (i=0 ; i<len ; i++)
+//             CRC_ProcessByte (&pr_crc, ((byte *)pr_progs)[i]);
+
+// byte swap the header
+#ifndef NOENDIAN
+       for (i=0 ; i<standard_dprograms_t_size/sizeof(int); i++)
+               ((int *)pr_progs)[i] = PRLittleLong ( ((int *)pr_progs)[i] );
+#endif
+
+       if (pr_progs->version == PROG_VERSION)
+       {
+//             printf("Opening standard progs file \"%s\"\n", filename);
+               current_progstate->intsize = 16;
+       }
+       else if (pr_progs->version == PROG_EXTENDEDVERSION)
+       {
+#ifndef NOENDIAN
+               for (i = standard_dprograms_t_size/sizeof(int); i < sizeof(dprograms_t)/sizeof(int); i++)
+                       ((int *)pr_progs)[i] = PRLittleLong ( ((int *)pr_progs)[i] );
+#endif
+               if (pr_progs->secondaryversion == PROG_SECONDARYVERSION16)
+               {
+//                     printf("Opening 16bit fte progs file \"%s\"\n", filename);
+                       current_progstate->intsize = 16;
+               }
+               else if (pr_progs->secondaryversion == PROG_SECONDARYVERSION32)
+               {
+//                     printf("Opening 32bit fte progs file \"%s\"\n", filename);
+                       current_progstate->intsize = 32;
+               }
+               else
+               {
+//                     printf("Opening KK7 progs file \"%s\"\n", filename);
+                       current_progstate->intsize = 24;        //KK progs. Yuck. Disabling saving would be a VERY good idea.
+                       pr_progs->version = PROG_VERSION;       //not fte.
+               }
+/*             else
+               {
+                       printf ("Progs extensions are not compatible\nTry recompiling with the FTE compiler\n");
+                       HunkFree(hmark);
+                       pr_progs=NULL;
+                       return false;
+               }
+*/     }
+       else
+       {
+               printf ("%s has wrong version number (%i should be %i)\n", filename, pr_progs->version, PROG_VERSION);
+               PRHunkFree(progfuncs, hmark);
+               pr_progs=NULL;
+               return false;
+       }
+
+//progs contains enough info for use to recompile it.
+       if (trysleft && (externs->autocompile == PR_COMPILECHANGED  || externs->autocompile == PR_COMPILEEXISTANDCHANGED) && pr_progs->version == PROG_EXTENDEDVERSION)
+       {
+               if (PR_TestRecompile(progfuncs))
+               {
+                       printf("Source file has changed\nRecompiling.\n");
+                       if (CompileFile(progfuncs, filename))
+                       {
+                               PRHunkFree(progfuncs, hmark);
+                               pr_progs=NULL;
+
+                               trysleft--;
+                               goto retry;
+                       }
+               }
+       }
+       if (!trysleft)  //the progs exists, let's just be happy about it.
+               printf("Progs is out of date and uncompilable\n");
+
+       if (headercrc != -1 && headercrc != 0)
+       if (pr_progs->crc != headercrc && pr_progs->crc != 0)   //This shouldn't affect us. However, it does adjust expectations and usage of builtins.
+       {
+//             printf ("%s system vars have been modified, progdefs.h is out of date\n", filename);
+               PRHunkFree(progfuncs, hmark);
+               pr_progs=NULL;
+               return false;
+       }
+
+       if (pr_progs->version == PROG_EXTENDEDVERSION && pr_progs->blockscompressed && !QC_decodeMethodSupported(2))
+       {
+               printf ("%s uses compression\n", filename);
+               PRHunkFree(progfuncs, hmark);
+               pr_progs=NULL;
+               return false;
+       }
+
+       fnc = pr_functions = (dfunction_t *)((qbyte *)pr_progs + pr_progs->ofs_functions);
+       pr_strings = ((char *)pr_progs + pr_progs->ofs_strings);
+       current_progstate->globaldefs = *(void**)&gd16 = (void *)((qbyte *)pr_progs + pr_progs->ofs_globaldefs);
+       current_progstate->fielddefs = *(void**)&fld16 = (void *)((qbyte *)pr_progs + pr_progs->ofs_fielddefs);
+       current_progstate->statements = (void *)((qbyte *)pr_progs + pr_progs->ofs_statements);
+
+       glob = pr_globals = (void *)((qbyte *)pr_progs + pr_progs->ofs_globals);
+
+       pr_linenums=NULL;
+       pr_types=NULL;
+       if (pr_progs->version == PROG_EXTENDEDVERSION)
+       {
+               if (pr_progs->ofslinenums)
+                       pr_linenums = (int *)((qbyte *)pr_progs + pr_progs->ofslinenums);
+               if (pr_progs->ofs_types)
+                       pr_types = (typeinfo_t *)((qbyte *)pr_progs + pr_progs->ofs_types);
+
+               //start decompressing stuff...
+               if (pr_progs->blockscompressed & 1)     //statements
+               {
+                       switch(current_progstate->intsize)
+                       {
+                       case 16:
+                               len=sizeof(dstatement16_t)*pr_progs->numstatements;
+                               break;
+                       case 32:
+                               len=sizeof(dstatement32_t)*pr_progs->numstatements;
+                               break;
+                       default:
+                               Sys_Error("Bad intsize");
+                       }
+                       s = PRHunkAlloc(progfuncs, len);
+                       QC_decode(progfuncs, PRLittleLong(*(int *)pr_statements16), len, 2, (char *)(((int *)pr_statements16)+1), s);
+
+                       current_progstate->statements = (dstatement16_t *)s;
+               }
+               if (pr_progs->blockscompressed & 2)     //global defs
+               {
+                       switch(current_progstate->intsize)
+                       {
+                       case 16:
+                               len=sizeof(ddef16_t)*pr_progs->numglobaldefs;
+                               break;
+                       case 32:
+                               len=sizeof(ddef32_t)*pr_progs->numglobaldefs;
+                               break;
+                       default:
+                               Sys_Error("Bad intsize");
+                       }
+                       s = PRHunkAlloc(progfuncs, len);
+                       QC_decode(progfuncs, PRLittleLong(*(int *)pr_globaldefs16), len, 2, (char *)(((int *)pr_globaldefs16)+1), s);
+
+                       gd16 = *(ddef16_t**)&current_progstate->globaldefs = (ddef16_t *)s;
+               }
+               if (pr_progs->blockscompressed & 4)     //fields
+               {
+                       switch(current_progstate->intsize)
+                       {
+                       case 16:
+                               len=sizeof(ddef16_t)*pr_progs->numglobaldefs;
+                               break;
+                       case 32:
+                               len=sizeof(ddef32_t)*pr_progs->numglobaldefs;
+                               break;
+                       default:
+                               Sys_Error("Bad intsize");
+                       }
+                       s = PRHunkAlloc(progfuncs, len);
+                       QC_decode(progfuncs, PRLittleLong(*(int *)pr_fielddefs16), len, 2, (char *)(((int *)pr_fielddefs16)+1), s);
+
+                       *(ddef16_t**)&current_progstate->fielddefs = (ddef16_t *)s;
+               }
+               if (pr_progs->blockscompressed & 8)     //functions
+               {
+                       len=sizeof(dfunction_t)*pr_progs->numfunctions;
+                       s = PRHunkAlloc(progfuncs, len);
+                       QC_decode(progfuncs, PRLittleLong(*(int *)pr_functions), len, 2, (char *)(((int *)pr_functions)+1), s);
+
+                       fnc = pr_functions = (dfunction_t *)s;
+               }
+               if (pr_progs->blockscompressed & 16)    //string table
+               {
+                       len=sizeof(char)*pr_progs->numstrings;
+                       s = PRHunkAlloc(progfuncs, len);
+                       QC_decode(progfuncs, PRLittleLong(*(int *)pr_strings), len, 2, (char *)(((int *)pr_strings)+1), s);
+
+                       pr_strings = (char *)s;
+               }
+               if (pr_progs->blockscompressed & 32)    //globals
+               {
+                       len=sizeof(float)*pr_progs->numglobals;
+                       s = PRHunkAlloc(progfuncs, len);
+                       QC_decode(progfuncs, PRLittleLong(*(int *)pr_globals), len, 2, (char *)(((int *)pr_globals)+1), s);
+
+                       glob = pr_globals = (float *)s;
+               }
+               if (pr_linenums && pr_progs->blockscompressed & 64)     //line numbers
+               {
+                       len=sizeof(int)*pr_progs->numstatements;
+                       s = PRHunkAlloc(progfuncs, len);
+                       QC_decode(progfuncs, PRLittleLong(*(int *)pr_linenums), len, 2, (char *)(((int *)pr_linenums)+1), s);
+
+                       pr_linenums = (int *)s;
+               }
+               if (pr_types && pr_progs->blockscompressed & 128)       //types
+               {
+                       len=sizeof(typeinfo_t)*pr_progs->numtypes;
+                       s = PRHunkAlloc(progfuncs, len);
+                       QC_decode(progfuncs, PRLittleLong(*(int *)pr_types), len, 2, (char *)(((int *)pr_types)+1), s);
+
+                       pr_types = (typeinfo_t *)s;
+               }
+       }
+
+       len=sizeof(char)*pr_progs->numstrings;
+       s = PRAddressableAlloc(progfuncs, len);
+       memcpy(s, pr_strings, len);
+       pr_strings = (char *)s;
+
+       len=sizeof(float)*pr_progs->numglobals;
+       s = PRAddressableAlloc(progfuncs, len);
+       memcpy(s, pr_globals, len);
+       glob = pr_globals = (float *)s;
+
+       if (progfuncs->stringtable)
+               stringadjust = pr_strings - progfuncs->stringtable;
+       else
+               stringadjust = 0;
+
+       if (!pr_linenums)
+       {
+               unsigned int lnotype = *(unsigned int*)"LNOF";
+               unsigned int version = 1;
+               int ohm;
+               unsigned int *file;
+               char lnoname[128];
+               ohm = PRHunkMark(progfuncs);
+
+               strcpy(lnoname, filename);
+               StripExtension(lnoname);
+               strcat(lnoname, ".lno");
+               if ((len=externs->FileSize(lnoname))>0)
+               {
+                       file = PRHunkAlloc(progfuncs, len+1);
+                       if (externs->ReadFile(lnoname, file, len+1))
+                       {
+                               if (    file[0] != lnotype
+                                       ||      file[1] != version
+                                       ||      file[2] != pr_progs->numglobaldefs
+                                       ||      file[3] != pr_progs->numglobals
+                                       ||      file[4] != pr_progs->numfielddefs
+                                       ||      file[5] != pr_progs->numstatements
+                                       )
+                               {
+                                       PRHunkFree(progfuncs, ohm);     //whoops: old progs or incompatible
+                               }
+                               else
+                                       pr_linenums = file + 6;
+                       }
+               }
+       }
+
+       pr_functions = fnc;
+//     pr_strings = ((char *)pr_progs + pr_progs->ofs_strings);
+       gd16 = *(ddef16_t**)&current_progstate->globaldefs = (ddef16_t *)((qbyte *)pr_progs + pr_progs->ofs_globaldefs);
+       fld16 = (ddef16_t *)((qbyte *)pr_progs + pr_progs->ofs_fielddefs);
+//     pr_statements16 = (dstatement16_t *)((qbyte *)pr_progs + pr_progs->ofs_statements);
+       pr_globals = glob;
+       st16 = pr_statements16;
+#undef pr_globals
+#undef pr_globaldefs16
+#undef pr_functions
+#undef pr_statements16
+#undef pr_fielddefs16
+
+
+       current_progstate->edict_size = pr_progs->entityfields * 4 + externs->edictsize;
+
+// byte swap the lumps
+       for (i=0 ; i<pr_progs->numfunctions; i++)
+       {
+#ifndef NOENDIAN
+               fnc[i].first_statement  = PRLittleLong (fnc[i].first_statement);
+               fnc[i].parm_start       = PRLittleLong (fnc[i].parm_start);
+               fnc[i].s_name   = (string_t)PRLittleLong ((long)fnc[i].s_name);
+               fnc[i].s_file   = (string_t)PRLittleLong ((long)fnc[i].s_file);
+               fnc[i].numparms = PRLittleLong (fnc[i].numparms);
+               fnc[i].locals   = PRLittleLong (fnc[i].locals);
+#endif
+/*             if (!strncmp(fnc[i].s_name+pr_strings, "ext_", 4))
+               {
+                       for (eb = extensionbuiltin; eb; eb = eb->prev)
+                       {
+                               if (*eb->name == '_')
+                               {
+                                       if (!strncmp(fnc[i].s_name+pr_strings+4, eb->name+1, strlen(eb->name+1)))
+                                       {
+                                               fnc[i].first_statement = -0x7fffffff;
+                                               *(void**)&fnc[i].profile = (void*)eb->func;
+                                               break;
+                                       }
+                               }
+                               else if (!strcmp(fnc[i].s_name+4, eb->name))
+                               {
+                                       fnc[i].first_statement = -0x7fffffff;
+                                       *(void**)&fnc[i].profile = (void*)eb->func;
+                                       break;
+                               }
+                       }
+               }
+*/
+               fnc[i].s_name += stringadjust;
+               fnc[i].s_file += stringadjust;
+       }
+
+       //actual global values
+#ifndef NOENDIAN
+       for (i=0 ; i<pr_progs->numglobals ; i++)
+               ((int *)glob)[i] = PRLittleLong (((int *)glob)[i]);
+#endif
+
+       if (pr_types)
+       {
+               for (i=0 ; i<pr_progs->numtypes ; i++)
+               {
+#ifndef NOENDIAN
+                       pr_types[i].type = PRLittleLong(current_progstate->types[i].type);
+                       pr_types[i].next = PRLittleLong(current_progstate->types[i].next);
+                       pr_types[i].aux_type = PRLittleLong(current_progstate->types[i].aux_type);
+                       pr_types[i].num_parms = PRLittleLong(current_progstate->types[i].num_parms);
+                       pr_types[i].ofs = PRLittleLong(current_progstate->types[i].ofs);
+                       pr_types[i].size = PRLittleLong(current_progstate->types[i].size);
+                       pr_types[i].name = (char *)PRLittleLong((long)current_progstate->types[i].name);
+#endif
+                       pr_types[i].name += stringadjust;
+               }
+       }
+
+       if (reorg)
+               reorg = (headercrc != -1);
+
+       QC_FlushProgsOffsets(progfuncs);
+       switch(current_progstate->intsize)
+       {
+       case 24:
+       case 16:
+               //byteswap the globals and fix name offsets
+               for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+               {
+#ifndef NOENDIAN
+                       gd16[i].type = PRLittleShort (gd16[i].type);
+                       gd16[i].ofs = PRLittleShort (gd16[i].ofs);
+                       gd16[i].s_name = (string_t)PRLittleLong ((long)gd16[i].s_name);
+#endif
+                       gd16[i].s_name += stringadjust;
+               }
+
+               //byteswap fields and fix name offets. Also register the fields (which will result in some offset adjustments in the globals segment).
+               for (i=0 ; i<pr_progs->numfielddefs ; i++)
+               {
+#ifndef NOENDIAN
+                       fld16[i].type = PRLittleShort (fld16[i].type);
+                       fld16[i].ofs = PRLittleShort (fld16[i].ofs);
+                       fld16[i].s_name = (string_t)PRLittleLong ((long)fld16[i].s_name);
+#endif
+                       if (reorg)
+                       {
+                               if (pr_types)
+                                       type = pr_types[fld16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type;
+                               else
+                                       type = fld16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
+
+                               if (progfuncs->fieldadjust && !pr_typecurrent)  //we need to make sure all fields appear in their original place.
+                                       QC_RegisterFieldVar(progfuncs, type, fld16[i].s_name+pr_strings, 4*(fld16[i].ofs+progfuncs->fieldadjust), -1);
+                               else if (type == ev_vector)     //emit vector vars early, so their fields cannot be alocated before the vector itself. (useful against scramblers)
+                               {
+                                       QC_RegisterFieldVar(progfuncs, type, fld16[i].s_name+pr_strings, -1, fld16[i].ofs);
+                               }
+                       }
+                       else
+                       {
+                               fdef_t *nf;
+                               if (numfields+1>maxfields)
+                               {
+                                       i = maxfields;
+                                       maxfields += 32;
+                                       nf = memalloc(sizeof(fdef_t) * maxfields);
+                                       memcpy(nf, field, sizeof(fdef_t) * i);
+                                       memfree(field);
+                                       field = nf;
+                               }
+                               nf = &field[numfields];
+                               nf->name = fld16[i].s_name+pr_strings;
+                               nf->type = fld16[i].type;
+                               nf->progsofs = fld16[i].ofs;
+                               nf->ofs = fld16[i].ofs;
+
+                               if (fields_size < (nf->ofs+type_size[nf->type])*4)
+                                       fields_size = (nf->ofs+type_size[nf->type])*4;
+
+                               numfields++;
+                       }
+                       fld16[i].s_name += stringadjust;
+               }
+               if (reorg && !(progfuncs->fieldadjust && !pr_typecurrent))
+               for (i=0 ; i<pr_progs->numfielddefs ; i++)
+               {
+                       if (pr_types)
+                               type = pr_types[fld16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type;
+                       else
+                               type = fld16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
+                       if (type != ev_vector)
+                               QC_RegisterFieldVar(progfuncs, type, fld16[i].s_name+pr_strings-stringadjust, -1, fld16[i].ofs);
+               }
+
+               break;
+       case 32:
+               for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+               {
+#ifndef NOENDIAN
+                       pr_globaldefs32[i].type = PRLittleLong (pr_globaldefs32[i].type);
+                       pr_globaldefs32[i].ofs = PRLittleLong (pr_globaldefs32[i].ofs);
+                       pr_globaldefs32[i].s_name = (string_t)PRLittleLong ((long)pr_globaldefs32[i].s_name);
+#endif
+                       pr_globaldefs32[i].s_name += stringadjust;
+               }
+
+               for (i=0 ; i<pr_progs->numfielddefs ; i++)
+               {
+       #ifndef NOENDIAN
+                       pr_fielddefs32[i].type = PRLittleLong (pr_fielddefs32[i].type);
+                       pr_fielddefs32[i].ofs = PRLittleLong (pr_fielddefs32[i].ofs);
+                       pr_fielddefs32[i].s_name = (string_t)PRLittleLong ((long)pr_fielddefs32[i].s_name);
+       #endif
+
+                       if (reorg)
+                       {
+                               if (pr_types)
+                                       type = pr_types[pr_fielddefs32[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type;
+                               else
+                                       type = pr_fielddefs32[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
+                               if (progfuncs->fieldadjust && !pr_typecurrent)  //we need to make sure all fields appear in their original place.
+                                       QC_RegisterFieldVar(progfuncs, type, fld16[i].s_name+pr_strings, 4*(fld16[i].ofs+progfuncs->fieldadjust), -1);
+                               else if (type == ev_vector)
+                                       QC_RegisterFieldVar(progfuncs, type, pr_fielddefs32[i].s_name+pr_strings, -1, pr_fielddefs32[i].ofs);
+                       }
+                       pr_fielddefs32[i].s_name += stringadjust;
+               }
+               if (reorg && !(progfuncs->fieldadjust && !pr_typecurrent))
+               for (i=0 ; i<pr_progs->numfielddefs ; i++)
+               {
+                       if (pr_types)
+                               type = pr_types[pr_fielddefs32[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type;
+                       else
+                               type = pr_fielddefs32[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
+                       if (type != ev_vector)
+                               QC_RegisterFieldVar(progfuncs, type, pr_fielddefs32[i].s_name+pr_strings-stringadjust, -1, pr_fielddefs32[i].ofs);
+               }
+               break;
+       default:
+               Sys_Error("Bad int size");
+       }
+
+//ifstring fixes arn't performed anymore.
+//the following switch just fixes endian and hexen2 calling conventions (by using different opcodes).
+       switch(current_progstate->intsize)
+       {
+       case 16:
+               for (i=0 ; i<pr_progs->numstatements ; i++)
+               {
+#ifndef NOENDIAN
+                       st16[i].op = PRLittleShort(st16[i].op);
+                       st16[i].a = PRLittleShort(st16[i].a);
+                       st16[i].b = PRLittleShort(st16[i].b);
+                       st16[i].c = PRLittleShort(st16[i].c);
+#endif
+                       if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8)
+                       {
+                               if (st16[i].b)
+                                       hexencalling = true;
+
+                       }
+               }
+               if (hexencalling)
+               {
+                       for (i=0 ; i<pr_progs->numstatements ; i++)
+                       {
+                               if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8)
+                                       st16[i].op += OP_CALL1H - OP_CALL1;
+                       }
+               }
+               break;
+
+       case 24:        //24 sucks. Guess why.
+               for (i=0 ; i<pr_progs->numstatements ; i++)
+               {
+#ifndef NOENDIAN
+                       pr_statements32[i].op = PRLittleLong(pr_statements32[i].op);
+                       pr_statements32[i].a = PRLittleLong(pr_statements32[i].a);
+                       pr_statements32[i].b = PRLittleLong(pr_statements32[i].b);
+                       pr_statements32[i].c = PRLittleLong(pr_statements32[i].c);
+#endif
+                       if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
+                       {
+                               if (pr_statements32[i].b)
+                                       hexencalling = true;
+
+                       }
+               }
+               if (hexencalling)
+               {
+                       for (i=0 ; i<pr_progs->numstatements ; i++)
+                       {
+                               if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
+                                       pr_statements32[i].op += OP_CALL1H - OP_CALL1;
+                       }
+               }
+               break;
+       case 32:
+               for (i=0 ; i<pr_progs->numstatements ; i++)
+               {
+#ifndef NOENDIAN
+                       pr_statements32[i].op = PRLittleLong(pr_statements32[i].op);
+                       pr_statements32[i].a = PRLittleLong(pr_statements32[i].a);
+                       pr_statements32[i].b = PRLittleLong(pr_statements32[i].b);
+                       pr_statements32[i].c = PRLittleLong(pr_statements32[i].c);
+#endif
+                       if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
+                       {
+                               if (pr_statements32[i].b)
+                                       hexencalling = true;
+
+                       }
+               }
+               if (hexencalling)
+               {
+                       for (i=0 ; i<pr_progs->numstatements ; i++)
+                       {
+                               if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8)
+                                       pr_statements32[i].op += OP_CALL1H - OP_CALL1;
+                       }
+               }
+               break;
+       }
+
+
+       if (headercrc == -1)
+       {
+               isfriked = true;
+               if (current_progstate->intsize != 16)
+                       Sys_Error("Decompiling a bigprogs");
+               return true;
+       }
+
+       progstype = current_progstate-pr_progstate;
+
+//     QC_StartShares(progfuncs);
+
+       isfriked = true;
+       if (!pr_typecurrent)    //progs 0 always acts as string stripped.
+               isfriked = -1;          //partly to avoid some bad progs.
+
+//     len = 0;
+       switch(current_progstate->intsize)
+       {
+       case 24:
+       case 16:
+               for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+               {
+                       if (pr_types)
+                               type = pr_types[gd16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type;
+                       else
+                               type = gd16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
+
+                       if (gd16[i].type & DEF_SHARED)
+                       {
+                               gd16[i].type &= ~DEF_SHARED;
+                               if (pr_types)
+                                       QC_AddSharedVar(progfuncs, gd16[i].ofs, pr_types[gd16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].size);
+                               else
+                                       QC_AddSharedVar(progfuncs, gd16[i].ofs, type_size[type]);
+                       }
+                       switch(type)
+                       {
+                       case ev_field:
+                               if (reorg)
+                                       QC_AddSharedFieldVar(progfuncs, i, pr_strings - stringadjust);
+                               break;
+                       case ev_string:
+                               if (((unsigned int *)glob)[gd16[i].ofs]>=progstate->progs->numstrings)
+                                       printf("Insane value\n");
+                               else if (isfriked != -1)
+                               {
+                                       if (pr_strings[((int *)glob)[gd16[i].ofs]])     //quakec uses string tables. 0 must remain null, or 'if (s)' can break.
+                                       {
+                                               ((int *)glob)[gd16[i].ofs] += stringadjust;
+                                               isfriked = false;
+                                       }
+                                       else
+                                               ((int *)glob)[gd16[i].ofs] = 0;
+                               }
+                               break;
+                       case ev_function:
+                               if (((int *)glob)[gd16[i].ofs]) //don't change null funcs
+                               {
+//                                     if (fnc[((int *)glob)[gd16[i].ofs]].first_statement>=0) //this is a hack. Make all builtins switch to the main progs first. Allows builtin funcs to cache vars from just the main progs.
+                                               ((int *)glob)[gd16[i].ofs] |= progstype << 24;
+                               }
+                               break;
+                       }
+               }
+               break;
+       case 32:
+               for (i=0 ; i<pr_progs->numglobaldefs ; i++)
+               {
+                       if (pr_types)
+                               type = pr_types[pr_globaldefs32[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type;
+                       else
+                               type = pr_globaldefs32[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
+
+                       if (pr_globaldefs32[i].type & DEF_SHARED)
+                       {
+                               pr_globaldefs32[i].type &= ~DEF_SHARED;
+                               if (pr_types)
+                                       QC_AddSharedVar(progfuncs, pr_globaldefs32[i].ofs, pr_types[pr_globaldefs32[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].size);
+                               else
+                                       QC_AddSharedVar(progfuncs, pr_globaldefs32[i].ofs, type_size[type]);
+                       }
+                       switch(type)
+                       {
+                       case ev_field:
+                               QC_AddSharedFieldVar(progfuncs, i, pr_strings - stringadjust);
+                               break;
+                       case ev_string:
+                               if (pr_strings[((int *)glob)[pr_globaldefs32[i].ofs]])  //quakec uses string tables. 0 must remain null, or 'if (s)' can break.
+                               {
+                                       ((int *)glob)[pr_globaldefs32[i].ofs] += stringadjust;
+                                       isfriked = false;
+                               }
+                               break;
+                       case ev_function:
+                               if (((int *)glob)[pr_globaldefs32[i].ofs])      //don't change null funcs
+                                       ((int *)glob)[pr_globaldefs32[i].ofs] |= progstype << 24;
+                               break;
+                       }
+               }
+
+               if (pr_progs->version == PROG_EXTENDEDVERSION && pr_progs->numbodylessfuncs)
+               {
+                       s = &((char *)pr_progs)[pr_progs->ofsbodylessfuncs];
+                       for (i = 0; i < pr_progs->numbodylessfuncs; i++)
+                       {
+                               d32 = ED_FindGlobal32(progfuncs, s);
+                               d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function);
+                               if (!d2)
+                                       Sys_Error("Runtime-linked function %s was not found in existing progs", s);
+                               if (!d32)
+                                       Sys_Error("Couldn't find def for \"%s\"", s);
+                               ((int *)glob)[d32->ofs] = (*(func_t *)&pr_progstate[0].globals[*d2]);
+
+                               s+=strlen(s)+1;
+                       }
+               }
+               break;
+       default:
+               Sys_Error("Bad int size");
+       }
+
+       if ((isfriked && pr_typecurrent))       //friked progs only allow one file.
+       {
+               printf("You are trying to load a string-stripped progs as an addon.\nThis behaviour is not supported. Try removing some optimizations.");
+               PRHunkFree(progfuncs, hmark);
+               pr_progs=NULL;
+               return false;
+       }
+
+       pr_strings+=stringadjust;
+       if (!progfuncs->stringtable)
+               progfuncs->stringtable = pr_strings;
+
+       if (progfuncs->stringtablesize + progfuncs->stringtable < pr_strings + pr_progs->numstrings)
+               progfuncs->stringtablesize = (pr_strings + pr_progs->numstrings) - progfuncs->stringtable;
+
+       eval = PR_FindGlobal(progfuncs, "thisprogs", progstype);
+       if (eval)
+               eval->prog = progstype;
+
+       switch(current_progstate->intsize)
+       {
+       case 16:
+               if (pr_progs->version == PROG_EXTENDEDVERSION && pr_progs->numbodylessfuncs)
+               {
+                       s = &((char *)pr_progs)[pr_progs->ofsbodylessfuncs];
+                       for (i = 0; i < pr_progs->numbodylessfuncs; i++)
+                       {
+                               d16 = ED_FindGlobal16(progfuncs, s);
+                               if (!d16)
+                               {
+                                       printf("Progs requires \"%s\" the external function \"%s\", but the definition was stripped", filename, s);
+                                       PRHunkFree(progfuncs, hmark);
+                                       pr_progs=NULL;
+                                       return false;
+                               }
+
+                               ((int *)glob)[d16->ofs] = PR_FindFunc(progfuncs, s, PR_ANY);
+                               if (!((int *)glob)[d16->ofs])
+                                       printf("Warning: Runtime-linked function %s was not found in primary progs (loading %s)", s, filename);
+                               /*
+                               d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function);
+                               if (!d2)
+                                       Sys_Error("Runtime-linked function %s was not found in primary progs (loading %s)", s, filename);
+                               ((int *)glob)[d16->ofs] = (*(func_t *)&pr_progstate[0].globals[*d2]);
+                               */
+                               s+=strlen(s)+1;
+                       }
+               }
+               break;
+       case 24:
+               break;  //cannot happen anyway.
+       case 32:
+               if (pr_progs->version == PROG_EXTENDEDVERSION && pr_progs->numbodylessfuncs)
+               {
+                       s = &((char *)pr_progs)[pr_progs->ofsbodylessfuncs];
+                       for (i = 0; i < pr_progs->numbodylessfuncs; i++)
+                       {
+                               d32 = ED_FindGlobal32(progfuncs, s);
+                               d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function);
+                               if (!d2)
+                                       printf("Warning: Runtime-linked function %s was not found in existing progs", s);
+                               if (!d32)
+                               {
+                                       printf("Couldn't find def for \"%s\"", s);
+                                       PRHunkFree(progfuncs, hmark);
+                                       pr_progs=NULL;
+                                       return false;
+                               }
+                               ((int *)glob)[d32->ofs] = (*(func_t *)&pr_progstate[0].globals[*d2]);
+
+                               s+=strlen(s)+1;
+                       }
+               }
+               break;
+       }
+
+       eval = PR_FindGlobal(progfuncs, "__ext__fasttrackarrays", PR_CURRENT);
+       if (eval)       //we support these opcodes
+               eval->_float = true;
+
+       return true;
+}
+
+
+
+struct edict_s *EDICT_NUM(progfuncs_t *progfuncs, unsigned int n)
+{
+       if (n >= maxedicts)
+               Sys_Error ("QCLIB: EDICT_NUM: bad number %i", n);
+
+       return prinst->edicttable[n];
+}
+
+unsigned int NUM_FOR_EDICT(progfuncs_t *progfuncs, struct edict_s *e)
+{
+       edictrun_t *er = (edictrun_t*)e;
+       if (er->entnum >= maxedicts)
+               Sys_Error ("QCLIB: NUM_FOR_EDICT: bad pointer (%p)", e);
+       return er->entnum;
+}
diff --git a/misc/mediasource/extra/fteqcc-src/pr_exec.c b/misc/mediasource/extra/fteqcc-src/pr_exec.c
new file mode 100644 (file)
index 0000000..bdd2af9
--- /dev/null
@@ -0,0 +1,1199 @@
+#define PROGSUSED
+#include "progsint.h"
+//#include "editor.h"
+
+#define HunkAlloc BADGDFG sdfhhsf FHS
+
+
+#define Host_Error Sys_Error
+
+
+//=============================================================================
+
+/*
+=================
+PR_PrintStatement
+=================
+*/
+/*
+void PR_PrintStatement (progfuncs_t *progfuncs, dstatement16_t *s)
+{
+       int             i;
+printf("PR_PrintStatement is unsupported\n");
+return;
+       if ( (unsigned)s->op < OP_NUMOPS)
+       {
+               printf ("%s ",  pr_opcodes[s->op].name);
+               i = strlen(pr_opcodes[s->op].name);
+               for ( ; i<10 ; i++)
+                       printf (" ");
+       }
+               
+       if (s->op == OP_IF || s->op == OP_IFNOT)
+               printf ("%sbranch %i",PR_GlobalString(progfuncs, s->a),s->b);
+       else if (s->op == OP_GOTO)
+       {
+               printf ("branch %i",s->a);
+       }
+       else if ( (unsigned)(s->op - OP_STORE_F) < 6)
+       {
+               printf ("%s",PR_GlobalString(progfuncs, s->a));
+               printf ("%s", PR_GlobalStringNoContents(progfuncs, s->b));
+       }
+       else
+       {
+               if (s->a)
+                       printf ("%s",PR_GlobalString(progfuncs, s->a));
+               if (s->b)
+                       printf ("%s",PR_GlobalString(progfuncs, s->b));
+               if (s->c)
+                       printf ("%s", PR_GlobalStringNoContents(progfuncs, s->c));
+       }
+       printf ("\n");
+}
+*/
+
+/*
+============
+PR_StackTrace
+============
+*/
+char *QC_ucase(char *str)
+{
+       static char s[1024];
+       strcpy(s, str);
+       str = s;
+
+       while(*str)
+       {
+               if (*str >= 'a' && *str <= 'z')
+                       *str = *str - 'a' + 'A';
+               str++;
+       }
+       return s;
+}
+
+void PR_StackTrace (progfuncs_t *progfuncs)
+{
+       dfunction_t     *f;
+       int                     i;
+       int progs;
+
+#ifdef STACKTRACE
+       int arg;
+       int *globalbase;
+#endif
+       progs = -1;
+       
+       if (pr_depth == 0)
+       {
+               printf ("<NO STACK>\n");
+               return;
+       }
+       
+#ifdef STACKTRACE
+       globalbase = (int *)pr_globals + pr_xfunction->parm_start - pr_xfunction->locals;
+#endif
+
+       pr_stack[pr_depth].f = pr_xfunction;
+       pr_stack[pr_depth].s = pr_xstatement;
+       for (i=pr_depth ; i>0 ; i--)
+       {
+               f = pr_stack[i].f;
+               
+               if (!f)
+               {
+                       printf ("<NO FUNCTION>\n");
+               }
+               else
+               {
+                       if (pr_stack[i].progsnum != progs)
+                       {
+                               progs = pr_stack[i].progsnum;
+
+                               printf ("<%s>\n", pr_progstate[progs].filename);
+                       }
+                       if (!f->s_file)
+                               printf ("stripped     : %s\n", f->s_name+progfuncs->stringtable);
+                       else
+                       {
+                               if (pr_progstate[progs].linenums)
+                                       printf ("%12s %i : %s\n", f->s_file+progfuncs->stringtable, pr_progstate[progs].linenums[pr_stack[i].s], f->s_name+progfuncs->stringtable);
+                               else
+                                       printf ("%12s : %s\n", f->s_file+progfuncs->stringtable, f->s_name+progfuncs->stringtable);
+                       }
+
+#ifdef STACKTRACE
+
+                       for (arg = 0; arg < f->locals; arg++)
+                       {
+                               ddef16_t *local;
+                               local = ED_GlobalAtOfs16(progfuncs, f->parm_start+arg);
+                               if (!local)
+                               {
+                                       printf("    ofs %i: %f : %i\n", f->parm_start+arg, *(float *)(globalbase - f->locals+arg), *(int *)(globalbase - f->locals+arg) );
+                               }
+                               else
+                               {
+                                       printf("    %s: %s\n", local->s_name+progfuncs->stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase - f->locals+arg)));
+                                       if (local->type == ev_vector)
+                                               arg+=2;
+                               }
+                       }
+
+                       if (i == pr_depth)
+                               globalbase = localstack + localstack_used;
+                       else
+                               globalbase -= f->locals;
+#endif
+               }
+       }
+}
+
+/*
+============
+PR_Profile_f
+
+============
+*/
+/*
+void PR_Profile_f (void)
+{
+       dfunction_t     *f, *best;
+       int                     max;
+       int                     num;
+       unsigned int                    i;
+
+       num = 0;
+       do
+       {
+               max = 0;
+               best = NULL;
+               for (i=0 ; i<pr_progs->numfunctions ; i++)
+               {
+                       f = &pr_functions[i];
+                       if (f->profile > max && f->first_statement >=0)
+                       {
+                               max = f->profile;
+                               best = f;
+                       }
+               }
+               if (best)
+               {
+                       if (num < 10)
+                               printf ("%7i %s\n", best->profile, best->s_name);
+                       num++;
+                       best->profile = 0;
+               }
+       } while (best);
+}
+*/
+
+
+/*
+============
+PR_RunError
+
+Aborts the currently executing function
+============
+*/
+void VARGS PR_RunError (progfuncs_t *progfuncs, char *error, ...)
+{
+       va_list         argptr;
+       char            string[1024];
+
+       va_start (argptr,error);
+       Q_vsnprintf (string,sizeof(string)-1, error,argptr);
+       va_end (argptr);
+
+//     {
+//             void SV_EndRedirect (void);
+//             SV_EndRedirect();
+//     }
+
+//     PR_PrintStatement (pr_statements + pr_xstatement);
+       PR_StackTrace (progfuncs);
+       printf ("\n");
+
+//editbadfile(pr_strings + pr_xfunction->s_file, -1);
+       
+//     pr_depth = 0;           // dump the stack so host_error can shutdown functions  
+//     prinst->exitdepth = 0;
+
+       Abort ("%s", string);
+}
+
+/*
+============================================================================
+PR_ExecuteProgram
+
+The interpretation main loop
+============================================================================
+*/
+
+/*
+====================
+PR_EnterFunction
+
+Returns the new program statement counter
+====================
+*/
+void   PR_AbortStack                   (progfuncs_t *progfuncs);
+int PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsnum)
+{
+       int             i, j, c, o;
+
+       pr_stack[pr_depth].s = pr_xstatement;
+       pr_stack[pr_depth].f = pr_xfunction;    
+       pr_stack[pr_depth].progsnum = progsnum;
+       pr_stack[pr_depth].pushed = pr_spushed;
+       pr_depth++;
+       if (pr_depth == MAX_STACK_DEPTH)
+       {
+               pr_depth--;
+               PR_StackTrace (progfuncs);
+
+               printf ("stack overflow on call to %s\n", progfuncs->stringtable+f->s_name);
+
+               //comment this out if you want the progs to try to continue anyway (could cause infinate loops)
+               PR_AbortStack(progfuncs);
+               Abort("Stack Overflow in %s\n", progfuncs->stringtable+f->s_name);
+               return pr_xstatement;
+       }
+
+       localstack_used += pr_spushed;  //make sure the call doesn't hurt pushed pointers
+
+// save off any locals that the new function steps on (to a side place, fromwhere they are restored on exit)
+       c = f->locals;
+       if (localstack_used + c > LOCALSTACK_SIZE)
+       {
+               localstack_used -= pr_spushed;
+               pr_depth--;
+               PR_RunError (progfuncs, "PR_ExecuteProgram: locals stack overflow\n");
+       }
+
+       for (i=0 ; i < c ; i++)
+               localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
+       localstack_used += c;
+
+// copy parameters (set initial values)
+       o = f->parm_start;
+       for (i=0 ; i<f->numparms ; i++)
+       {
+               for (j=0 ; j<f->parm_size[i] ; j++)
+               {
+                       ((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
+                       o++;
+               }
+       }
+
+       pr_xfunction = f;
+       return f->first_statement - 1;  // offset the s++
+}
+
+/*
+====================
+PR_LeaveFunction
+====================
+*/
+int PR_LeaveFunction (progfuncs_t *progfuncs)
+{
+       int             i, c;
+
+       if (pr_depth <= 0)
+               Sys_Error ("prog stack underflow");
+
+// restore locals from the stack
+       c = pr_xfunction->locals;
+       localstack_used -= c;
+       if (localstack_used < 0)
+               PR_RunError (progfuncs, "PR_ExecuteProgram: locals stack underflow\n");
+
+       for (i=0 ; i < c ; i++)
+               ((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
+
+// up stack
+       pr_depth--;
+       PR_MoveParms(progfuncs, pr_stack[pr_depth].progsnum, pr_typecurrent);
+       PR_SwitchProgs(progfuncs, pr_stack[pr_depth].progsnum);
+       pr_xfunction = pr_stack[pr_depth].f;
+       pr_spushed = pr_stack[pr_depth].pushed;
+
+       localstack_used -= pr_spushed;
+       return pr_stack[pr_depth].s;
+}
+
+ddef32_t *ED_FindLocalOrGlobal(progfuncs_t *progfuncs, char *name, eval_t **val)
+{
+       static ddef32_t def;
+       ddef32_t *def32;
+       ddef16_t *def16;
+       int i;
+
+       switch (pr_progstate[pr_typecurrent].intsize)
+       {
+       case 16:
+       case 24:
+               //this gets parms fine, but not locals
+               if (pr_xfunction)
+               for (i = 0; i < pr_xfunction->numparms; i++)
+               {
+                       def16 = ED_GlobalAtOfs16(progfuncs, pr_xfunction->parm_start+i);
+                       if (!def16)
+                               continue;
+                       if (!strcmp(def16->s_name+progfuncs->stringtable, name))
+                       {
+                               *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[pr_xfunction->parm_start+i];
+
+                               //we need something like this for functions that are not the top layer
+       //                      *val = (eval_t *)&localstack[localstack_used-pr_xfunction->numparms*4];
+                               def.ofs = def16->ofs;
+                               def.s_name = def16->s_name;
+                               def.type = def16->type;
+                               return &def;
+                       }
+               }
+               def16 = ED_FindGlobal16(progfuncs, name);
+               if (!def16)
+                       return NULL;
+               def.ofs = def16->ofs;
+               def.type = def16->type;
+               def.s_name = def16->s_name;
+               def32 = &def;
+               break;
+       case 32:
+               //this gets parms fine, but not locals
+               if (pr_xfunction)
+               for (i = 0; i < pr_xfunction->numparms; i++)
+               {
+                       def32 = ED_GlobalAtOfs32(progfuncs, pr_xfunction->parm_start+i);
+                       if (!def32)
+                               continue;
+                       if (!strcmp(def32->s_name+progfuncs->stringtable, name))
+                       {
+                               *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[pr_xfunction->parm_start+i];
+
+                               //we need something like this for functions that are not the top layer
+       //                      *val = (eval_t *)&localstack[localstack_used-pr_xfunction->numparms*4];
+                               return def32;
+                       }
+               }
+               def32 = ED_FindGlobal32(progfuncs, name);
+               if (!def32)
+                       return NULL;
+               break;
+       default:
+               Sys_Error("Bad int size in ED_FindLocalOrGlobal");
+               def32 = NULL;
+       }
+       
+       *val = (eval_t *)&pr_progstate[pr_typecurrent].globals[def32->ofs];
+       return &def;
+}
+
+char *COM_TrimString(char *str)
+{
+       int i;
+       static char buffer[256];
+       while (*str <= ' ' && *str>'\0')
+               str++;
+
+       for (i = 0; i < 255; i++)
+       {
+               if (*str <= ' ')
+                       break;
+               buffer[i] = *str++;
+       }
+       buffer[i] = '\0';
+       return buffer;
+}
+
+char *EvaluateDebugString(progfuncs_t *progfuncs, char *key)
+{
+       static char buf[256];
+       char *c, *c2;
+       ddef32_t *def;
+       fdef_t *fdef;
+       eval_t *val;
+       char *assignment;
+       int type;
+       ddef32_t fakedef;
+       eval_t fakeval;
+
+       assignment = strchr(key, '=');
+       if (assignment)
+               *assignment = '\0';
+
+       c = strchr(key, '.');
+       if (c) *c = '\0';
+       def = ED_FindLocalOrGlobal(progfuncs, key, &val);       
+       if (!def)
+       {
+               if (atoi(key))
+               {
+                       def = &fakedef;
+                       def->ofs = 0;
+                       def->type = ev_entity;
+                       val = &fakeval;
+                       val->edict = atoi(key);
+               }
+       }
+       if (c) *c = '.';
+       if (!def)
+       {               
+               return "(Bad string)";
+       }       
+       type = def->type;
+
+       //go through ent vars
+       c = strchr(key, '.');   
+       while(c)
+       {
+               c2 = c+1;
+               c = strchr(c2, '.');
+               type = type &~DEF_SAVEGLOBAL;
+               if (current_progstate->types)
+                       type = current_progstate->types[type].type;
+               if (type != ev_entity)
+                       return "'.' without entity";
+               if (c)*c = '\0';
+               fdef = ED_FindField(progfuncs, COM_TrimString(c2));
+               if (c)*c = '.';
+               if (!fdef)
+                       return "(Bad string)";
+               val = (eval_t *) (((char *)PROG_TO_EDICT(progfuncs, val->_int)->fields) + fdef->ofs*4);         
+               type = fdef->type;
+       }
+       
+       if (assignment)
+       {
+               assignment++;
+               switch (type&~DEF_SAVEGLOBAL)
+               {
+               case ev_string:
+                       *(string_t *)val = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, assignment, 0));
+                       break;
+                       
+               case ev_float:
+                       *(float *)val = (float)atof (assignment);
+                       break;
+
+               case ev_integer:
+                       *(int *)val = atoi (assignment);
+                       break;
+                       
+/*             case ev_vector:
+                       strcpy (string, assignment);
+                       v = string;
+                       w = string;
+                       for (i=0 ; i<3 ; i++)
+                       {
+                               while (*v && *v != ' ')
+                                       v++;
+                               *v = 0;
+                               ((float *)d)[i] = (float)atof (w);
+                               w = v = v+1;
+                       }
+                       break;
+*/
+               case ev_entity:
+                       *(int *)val = EDICT_TO_PROG(progfuncs, EDICT_NUM(progfuncs, atoi (assignment)));
+                       break;
+
+               case ev_field:
+                       fdef = ED_FindField (progfuncs, assignment);
+                       if (!fdef)
+                       {
+                               int l,nl = strlen(assignment);
+                               strcpy(buf, "Can't find field ");
+                               l = strlen(buf);
+                               if (nl > sizeof(buf)-l-2)
+                                       nl = sizeof(buf)-l-2;
+                               memcpy(buf+l, assignment, nl);
+                               assignment[l+nl+0] = '\n';
+                               assignment[l+nl+1] = 0;
+                               return buf;
+                       }
+                       *(int *)val = G_INT(fdef->ofs);
+                       break;
+
+               case ev_function:
+                       {
+                               dfunction_t *func;
+                               int i;
+                               int progsnum = -1;
+                               char *s = assignment;
+                               if (s[0] && s[1] == ':')
+                               {
+                                       progsnum = atoi(s);
+                                       s+=2;
+                               }
+                               else if (s[0] && s[1] && s[2] == ':')
+                               {
+                                       progsnum = atoi(s);
+                                       s+=3;
+                               }
+
+                               func = ED_FindFunction (progfuncs, s, &i, progsnum);
+                               if (!func)
+                               {
+                                       int l,nl = strlen(s);
+
+                                       assignment[-1] = '=';
+
+                                       strcpy(buf, "Can't find field ");
+                                       l = strlen(buf);
+                                       if (nl > sizeof(buf)-l-2)
+                                               nl = sizeof(buf)-l-2;
+                                       memcpy(buf+l, assignment, nl);
+                                       assignment[l+nl+0] = '\n';
+                                       assignment[l+nl+1] = 0;
+                                       return buf;
+                               }
+                               *(func_t *)val = (func - pr_progstate[i].functions) | (i<<24);
+                       }
+                       break;
+
+               default:
+                       break;
+
+               }
+               assignment[-1] = '=';
+       }
+       strcpy(buf, PR_ValueString(progfuncs, type, val));
+
+       return buf;
+}
+
+int debugstatement;
+//int EditorHighlightLine(window_t *wnd, int line);
+void SetExecutionToLine(progfuncs_t *progfuncs, int linenum)
+{
+       int pn = pr_typecurrent;
+       int snum;
+       dfunction_t *f = pr_xfunction;
+
+       switch(current_progstate->intsize)
+       {
+       case 16:
+               for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++) 
+               {
+                       if (pr_statements16[snum].op == OP_DONE)
+                               return;
+               }
+               break;
+       case 24:
+       case 32:
+               for (snum = f->first_statement; pr_progstate[pn].linenums[snum] < linenum; snum++) 
+               {
+                       if (pr_statements32[snum].op == OP_DONE)
+                               return;
+               }
+               break;
+       default:
+               Sys_Error("Bad intsize");
+               snum = 0;
+       }
+       debugstatement = snum;
+//     EditorHighlightLine(editwnd, pr_progstate[pn].linenums[snum]);
+}
+
+//0 clear. 1 set, 2 toggle, 3 check
+int PR_ToggleBreakpoint(progfuncs_t *progfuncs, char *filename, int linenum, int flag) //write alternate route to work by function name.
+{
+       int ret=0;
+       unsigned int fl;
+       unsigned int i;
+       int pn = pr_typecurrent;
+       dfunction_t *f;
+       int op;
+
+       for (pn = 0; (unsigned)pn < maxprogs; pn++)
+       {
+               if (!pr_progstate || !pr_progstate[pn].progs)
+                       continue;
+
+               if (linenum)    //linenum is set means to set the breakpoint on a file and line
+               {
+                       if (!pr_progstate[pn].linenums)
+                               continue;
+
+                       for (f = pr_progstate[pn].functions, fl = 0; fl < pr_progstate[pn].progs->numfunctions; f++, fl++)
+                       {
+                               if (!stricmp(f->s_file+progfuncs->stringtable, filename))
+                               {
+                                       for (i = f->first_statement; ; i++)
+                                       {
+                                               if (pr_progstate[pn].linenums[i] >= linenum)
+                                               {
+                                                       fl = pr_progstate[pn].linenums[i];
+                                                       for (; ; i++)
+                                                       {
+                                                               if ((unsigned int)pr_progstate[pn].linenums[i] > fl)
+                                                                       break;
+
+                                                               switch(pr_progstate[pn].intsize)
+                                                               {
+                                                               case 16:
+                                                                       op = ((dstatement16_t*)pr_progstate[pn].statements + i)->op;
+                                                                       break;
+                                                               case 24:
+                                                               case 32:
+                                                                       op = ((dstatement32_t*)pr_progstate[pn].statements + i)->op;
+                                                                       break;
+                                                               default:
+                                                                       Sys_Error("Bad intsize");
+                                                                       op = 0;
+                                                               }
+                                                               switch (flag)
+                                                               {
+                                                               default:
+                                                                       if (op & 0x8000)
+                                                                       {
+                                                                               op &= ~0x8000;
+                                                                               ret = false;
+                                                                               flag = 0;
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               op |= 0x8000;
+                                                                               ret = true;
+                                                                               flag = 1;
+                                                                       }
+                                                                       break;
+                                                               case 0:
+                                                                       op &= ~0x8000;
+                                                                       ret = false;
+                                                                       break;
+                                                               case 1:
+                                                                       op |= 0x8000;
+                                                                       ret = true;
+                                                                       break;
+                                                               case 3:
+                                                                       if (op & 0x8000)
+                                                                               return true;
+                                                               }
+                                                               switch(pr_progstate[pn].intsize)
+                                                               {
+                                                               case 16:
+                                                                       ((dstatement16_t*)pr_progstate[pn].statements + i)->op = op;
+                                                                       break;
+                                                               case 24:
+                                                               case 32:
+                                                                       ((dstatement32_t*)pr_progstate[pn].stat