Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

104211
LINES
[SHOW ALL]

< > BotCompany Repo | #1005016 - Mocha Doom Single Source (include)

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Libraryless. Compilation Failed (104211L/700K).

package utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;

import p.Resettable;
import w.InputStreamSugar;

/**
 * Some utilities that emulate C stlib methods or provide convenient functions
 * to do repetitive system and memory related stuff.
 * 
 * @author Maes
 */

public final class C2JUtils {

    static public final char[] strcpy(char[] s1, final char[] s2) {
        for (int i = 0; i < Math.min(s1.length, s2.length); i++) {
            s1[i] = s2[i];
        }
        return s1;
    }

    static public final char[] strcpy(char[] s1, final char[] s2, int off, int len) {
        for (int i = 0; i < len; i++) {
            s1[i] = s2[i + off];
        }
        return s1;
    }

    static public final char[] strcpy(char[] s1, final char[] s2, int off) {
        for (int i = 0; i < Math.min(s1.length, s2.length - off); i++) {
            s1[i] = s2[i + off];
        }
        return s1;
    }

    static public final char[] strcpy(char[] s1, String s2) {
        for (int i = 0; i < Math.min(s1.length, s2.length()); i++) {
            s1[i] = s2.charAt(i);
        }
        return s1;
    }

    
    /** Return a byte[] array from the string's chars,
     *  ANDed to the lowest 8 bits.
     * 
     * @param str
     * @return
     */
    public static final byte[] toByteArray(String str) {
        byte[] retour = new byte[str.length()];
        for (int i = 0; i < str.length(); i++) {
            retour[i] = (byte) (str.charAt(i) & 0xFF);
        }
        return retour;
    }

    /**
     * Finds index of first element of array matching key. Useful whenever an
     * "indexOf" property is required or you encounter the C-ism [pointer-
     * array_base] used to find array indices in O(1) time. However, since this
     * is just a dumb unsorted search, running time is O(n), so use this method
     * only sparingly and in scenarios where it won't occur very frequently
     * -once per level is probably OK-, but watch out for nested loops, and
     * cache the result whenever possible. Consider adding an index or ID type
     * of field to the searched type if you require to use this property too
     * often.
     * 
     * @param array
     * @param key
     * @return
     */

    public static int indexOf(Object[] array, Object key) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == key) {
                return i;
            }
        }

        return -1;
    }

    /**
     * Emulates C-style "string comparison". "Strings" are considered
     * null-terminated, and comparison is performed only up to the smaller of
     * the two.
     * 
     * @param s1
     * @param s2
     * @return
     */

    static public final boolean strcmp(char[] s1, final char[] s2) {
        boolean match = true;
        for (int i = 0; i < Math.min(s1.length, s2.length); i++) {
            if (s1[i] != s2[i]) {
                match = false;
                break;
            }
        }
        return match;
    }

    static public final boolean strcmp(char[] s1, String s2) {
        return strcmp(s1, s2.toCharArray());
    }

    /**
     * C-like string length (null termination).
     * 
     * @param s1
     * @return
     */
    static public final int strlen(char[] s1) {
        if (s1 == null)
            return 0;
        int len = 0;

        while (s1[len++] > 0) {
            if (len >= s1.length)
                break;
        }

        return len - 1;
    }

    /**
     * Return a new String based on C-like null termination.
     * 
     * @param s
     * @return
     */
    static public final String nullTerminatedString(char[] s) {
        if (s == null)
            return "";
        int len = 0;

        while (s[len++] > 0) {
            if (len >= s.length)
                break;
        }

        return new String(s, 0, len - 1);
    }

    /**
     * Automatically "initializes" arrays of objects with their default
     * constuctor. It's better than doing it by hand, IMO. If you have a better
     * way, be my guest.
     * 
     * @param os
     * @param c
     * @throws Exception
     * @throws
     */

    public static final <T> void initArrayOfObjects(T[] os, Class<T> c) {
        try {
            for (int i = 0; i < os.length; i++) {
                os[i] = c.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Failure to allocate " + os.length
                    + " objects of class" + c.getName() + "!");
            System.exit(-1);
        }
    }

    /**
     * Automatically "initializes" arrays of objects with their default
     * constuctor. It's better than doing it by hand, IMO. If you have a better
     * way, be my guest.
     * 
     * @param os
     * @throws Exception
     * @throws
     */

    public static final <T> void initArrayOfObjects(T[] os) {
        Class<T> c = (Class<T>) os.getClass().getComponentType();
        try {
            for (int i = 0; i < os.length; i++) {
                os[i] = (T) c.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Failure to allocate " + os.length
                    + " objects of class " + c.getName() + "!");

            System.exit(-1);
        }
    }

    /**
     * Uses reflection to automatically create and initialize an array of
     * objects of the specified class. Does not require casting on "reception".
     * 
     * @param <T>
     * @param c
     * @param num
     * @return
     * @return
     */

    public static final <T> T[] createArrayOfObjects(Class<T> c, int num) {
        T[] os = null;

        os=getNewArray(c,num);

        try {
            for (int i = 0; i < os.length; i++) {
                os[i] = (T) c.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Failure to instantiate " + os.length
                    + " objects of class " + c.getName() + "!");
            System.exit(-1);
        }

        return os;
    }
    
    /**
     * Uses reflection to automatically create and initialize an array of
     * objects of the specified class. Does not require casting on "reception".
     * Requires an instance of the desired class. This allows getting around
     * determining the runtime type of parametrized types.
     * 
     * 
     * @param <T>
     * @param instance An instance of a particular class. 
     * @param num
     * @return
     * @return
     */

    @SuppressWarnings("unchecked")
    public static final <T> T[] createArrayOfObjects(T instance, int num) {
        T[] os = null;
        
        Class<T> c=(Class<T>) instance.getClass();

        os=getNewArray(c,num);

        try {
            for (int i = 0; i < os.length; i++) {
                os[i] = (T) c.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Failure to instantiate " + os.length
                    + " objects of class " + c.getName() + "!");
            System.exit(-1);
        }

        return os;
    }


    /**
     * Automatically "initializes" arrays of objects with their default
     * constuctor. It's better than doing it by hand, IMO. If you have a better
     * way, be my guest.
     * 
     * @param os
     * @param startpos inclusive
     * @param endpos non-inclusive
     * @throws Exception
     * @throws
     */

    public static final<T> void initArrayOfObjects(T[] os, int startpos,
            int endpos) {
        @SuppressWarnings("unchecked")
		Class<T> c = (Class<T>) os.getClass().getComponentType();
        try {
            for (int i = startpos; i < endpos; i++) {
                os[i] = c.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Failure to allocate " + os.length
                    + " objects of class " + c.getName() + "!");

            System.exit(-1);
        }
    }

    /** This method gets eventually inlined, becoming very fast */

    public static final int toUnsignedByte(byte b) {
        return (0x000000FF & b);
    }

    // Optimized array-fill methods designed to operate like C's memset.

    public static final void memset(boolean[] array, boolean value, int len) {
        if (len > 0)
            array[0] = value;
        for (int i = 1; i < len; i += i) {
            System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i)
                    : i);
        }
    }

    public static final void memset(char[] array, char value, int len) {
        if (len > 0)
            array[0] = value;
        for (int i = 1; i < len; i += i) {
            System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i)
                    : i);
        }
    }

    public static final void memset(int[] array, int value, int len) {
        if (len > 0)
            array[0] = value;
        for (int i = 1; i < len; i += i) {
            System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i)
                    : i);
        }
    }
    
    public static final void memset(short[] array, short value, int len) {
        if (len > 0)
            array[0] = value;
        for (int i = 1; i < len; i += i) {
            System.arraycopy(array, 0, array, i, ((len - i) < i) ? (len - i)
                    : i);
        }
    }

    public static final long unsigned(int num) {
        return 0xFFFFFFFFL & num;
    }

    public static final char unsigned(short num) {
        return (char) num;
    }

    /**
     * Convenient alias for System.arraycopy(src, 0, dest, 0, length);
     * 
     * @param dest
     * @param src
     * @param length
     */
    public static final void memcpy(Object dest, Object src, int length) {
        System.arraycopy(src, 0, dest, 0, length);
    }

    public static final boolean testReadAccess(String URI) {
    	InputStream in=null;
    	
        // This is bullshit.
        if (URI == null)
            return false;
        if (URI.length() == 0)
            return false;

        try {
            in=new FileInputStream(URI);
        } catch (Exception e) {
            // Not a file...
            URL u;
			try {
				u = new URL(URI);
			} catch (MalformedURLException e1) {
				return false;
			}
            try {
				in=u.openConnection().getInputStream();
			} catch (IOException e1) {
				return false;
			}

        }
        
        if (in!=null) {
        	try {
				in.close();
			} catch (IOException e) {

			}
        	return true;
        }
        // All is well. Go on...
        return true;

    }
    
    public static final boolean testWriteAccess(String URI) {
    	OutputStream out=null;
    	
        // This is bullshit.
        if (URI == null)
            return false;
        if (URI.length() == 0)
            return false;

        try {
            out=new FileOutputStream(URI);
        } catch (Exception e) {
            // Not a file...
            URL u;
			try {
				u = new URL(URI);
			} catch (MalformedURLException e1) {
				return false;
			}
            try {
				out=u.openConnection().getOutputStream();
			} catch (IOException e1) {
				return false;
			}

        }

        if (out!=null) {
        	try {
				out.close();
			} catch (IOException e) {

			}
        	return true;
        }
        // All is well. Go on...
        return true;
    }

    /**
     * Returns true if flags are included in arg. Synonymous with (flags &
     * arg)!=0
     * 
     * @param flags
     * @param arg
     * @return
     */
    public static final boolean flags(int flags, int arg) {
        return ((flags & arg) != 0);
    }
    
    public static final boolean flags(long flags, long arg) {
        return ((flags & arg) != 0);
    }

    /**
     * Returns 1 for true and 0 for false. Useful, given the amount of
     * "arithmetic" logical functions in legacy code. Synonymous with
     * (expr?1:0);
     * 
     * @param flags
     * @param arg
     * @return
     */
    public static final int eval(boolean expr) {
        return (expr ? 1 : 0);
    }

    /**
     * Returns 1 for non-null and 0 for null objects. Useful, given the amount
     * of "existential" logical functions in legacy code. Synonymous with
     * (expr!=null);
     * 
     * @param flags
     * @param arg
     * @return
     */
    public static final boolean eval(Object expr) {
        return (expr != null);
    }

    /**
     * Returns true for expr!=0, false otherwise.
     * 
     * @param flags
     * @param arg
     * @return
     */
    public static final boolean eval(int expr) {
        return expr != 0;
    }

    /**
     * Returns true for expr!=0, false otherwise.
     * 
     * @param flags
     * @param arg
     * @return
     */
    public static final boolean eval(long expr) {
        return expr != 0;
    }

    public static final void resetAll(Resettable[] r) {
        for (int i = 0; i < r.length; i++) {
            r[i].reset();
        }
    }

    /**
     * Useful for unquoting strings, since StringTokenizer won't do it for us.
     * Returns null upon any failure.
     * 
     * @param s
     * @param c
     * @return
     */

    public static final String unquote(String s, char c) {

        int firstq = s.indexOf(c);
        int lastq = s.lastIndexOf(c);
        // Indexes valid?
        if (isQuoted(s,c))
                return s.substring(firstq + 1, lastq);
        
        return null;
    }

    public static final boolean isQuoted(String s, char c) {

        int q1 = s.indexOf(c);
        int q2 = s.lastIndexOf(c);
        char c1,c2;
        
        // Indexes valid?
        if (q1 != -1 && q2 != -1) {
            if (q1 < q2) {
                c1=s.charAt(q1);
                c2=s.charAt(q2);
                return (c1==c2);
            }
        }
        
        return false;
    }
    
    public static final String unquoteIfQuoted(String s, char c) {

        String tmp = unquote(s, c);
        if (tmp != null)
            return tmp;
        return s;
    }

    /** Return either 0 or a hashcode 
     * 
     * @param o 
     */
    public static final int pointer(Object o) {
        if (o == null)
            return 0;
        else
            return o.hashCode();
    }

 
    public static final boolean checkForExtension(String filename, String ext) {
        
        // Null filenames satisfy null extensions.
        if ((filename == null || filename.isEmpty())
                && (ext == null || ext.isEmpty()))
            return true;
        
        String separator = System.getProperty("file.separator");

        // Remove the path upto the filename.
        int lastSeparatorIndex = filename.lastIndexOf(separator);
        if (lastSeparatorIndex != -1) {
            filename = filename.substring(lastSeparatorIndex + 1);
        }

        String realext = null;

        // Get extension separator. It SHOULD be . on all platforms, right?
        int pos = filename.lastIndexOf('.');

        if (pos >= 0 && pos <= filename.length() - 2) { // Extension present
            
            // Null comparator on valid extension
            if (ext == null || ext.isEmpty()) return false;
            
            realext = filename.substring(pos + 1);
            return realext.compareToIgnoreCase(ext) == 0;
        } else // No extension, and null/empty comparator
        if (ext == null || ext.isEmpty())
            return true;

        // No extension, and non-null/nonempty comparator.
        return false;
    }    
    
    /** Return the filename without extension, and stripped
     * of the path.
     * 
     * @param s
     * @return
     */
    
    public static final String removeExtension(String s) {

        String separator = System.getProperty("file.separator");
        String filename;

        // Remove the path upto the filename.
        int lastSeparatorIndex = s.lastIndexOf(separator);
        if (lastSeparatorIndex == -1) {
            filename = s;
        } else {
            filename = s.substring(lastSeparatorIndex + 1);
        }

        // Remove the extension.
        int extensionIndex = filename.lastIndexOf(".");
        if (extensionIndex == -1)
            return filename;

        return filename.substring(0, extensionIndex);
    }

    
    /**
     * This method is supposed to return the "name" part of a filename. It was
     * intended to return length-limited (max 8 chars) strings to use as lump
     * indicators. There's normally no need to enforce this behavior, as there's
     * nothing preventing the engine from INTERNALLY using lump names with >8
     * chars. However, just to be sure...
     * 
     * @param path
     * @param limit  Set to any value >0 to enforce a length limit
     * @param whole keep extension if set to true
     * @return
     */

    public static final String extractFileBase(String path, int limit, boolean whole) {
    	
    	if (path==null) return path;
    	
        int src = path.length() - 1;

        String separator = System.getProperty("file.separator");
        src = path.lastIndexOf(separator)+1;

        if (src < 0) // No separator
            src = 0;

        int len = path.lastIndexOf('.');
        if (whole || len<0 ) len=path.length()-src; // No extension.
        else  len-= src;        

        // copy UP to the specific number of characters, or all        
        if (limit > 0) len = Math.min(limit, len);
        
        return path.substring(src, src + len);
    }

    /** Maes: File intead of "inthandle" */

    public static long filelength(File handle) {
        try {
            return handle.length();
        } catch (Exception e) {
            System.err.println("Error fstating");
            return -1;
        }

    }

	@SuppressWarnings("unchecked")
	public static final <T> T[] resize(T[] oldarray, int newsize) {
		
		if (oldarray[0]!=null) return resize(oldarray[0],oldarray,newsize); 
		
		T cls=null;
		try {
			cls = (T) oldarray.getClass().getComponentType().newInstance();
			return resize(cls,oldarray,newsize);
		} catch (Exception e) {
			System.err.println("Cannot autodetect type in resizeArray.\n");
			return null;
		}


	}
    
	/** Generic array resizing method. Calls Arrays.copyOf but then also
	 *  uses initArrayOfObject for the "abundant" elements.
	 * 
	 * @param <T>
	 * @param instance
	 * @param oldarray
	 * @param newsize
	 * @return
	 */
	
	public static final <T> T[] resize(T instance,T[] oldarray, int newsize) {
		
		//  Hmm... nope.
		if (newsize<=oldarray.length) return oldarray;
		
		// Copy old array with built-in stuff.
		T[] tmp =Arrays.copyOf(oldarray,newsize);
		
		// Init the null portions as well
		C2JUtils.initArrayOfObjects(tmp, oldarray.length,tmp.length);

		System.out.printf("Old array of type %s resized. New capacity: %d\n"
				,instance.getClass(),newsize);
		
		return tmp;

	}
	
	/** Resize an array without autoinitialization. Same as Arrays.copyOf(..), just
	 * prints a message.
	 *  
	 * @param <T>
	 * @param oldarray
	 * @param newsize
	 * @return
	 */
	
	public static final <T> T[] resizeNoAutoInit(T[] oldarray, int newsize) {
		
		// For non-autoinit types, this is enough.
		T[] tmp =Arrays.copyOf(oldarray,newsize);
		
		System.out.printf("Old array of type %s resized without auto-init. New capacity: %d\n"
				,tmp.getClass().getComponentType(),newsize);
		
		return tmp;

	}
	
	@SuppressWarnings("unchecked")
	public final static<T> T[] getNewArray(T instance,int size){
		
		T[] os=null;
		Class<T> c=(Class<T>) instance.getClass();
		
        try {
            os = (T[]) Array.newInstance(c, size);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Failure to allocate " + size
                    + " objects of class " + c.getName() + "!");
            System.exit(-1);
        }
        
        return os;
	}
	
	public final static<T> T[] getNewArray(int size,T instance){
		@SuppressWarnings("unchecked")
		Class<T> c=(Class<T>) instance.getClass();
		return getNewArray(c,size);
	}
	
	@SuppressWarnings("unchecked")
	public final static<T> T[] getNewArray(Class<T> c,int size){
		T[] os=null;
        try {
            os = (T[]) Array.newInstance(c, size);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Failure to allocate " + size
                    + " objects of class " + c.getName() + "!");
            System.exit(-1);
        }
        
        return os;
	}

    /**
     * Try to guess whether a URI represents a local file, a network any of the
     * above but zipped. Returns
     * 
     * @param URI
     * @return an int with flags set according to InputStreamSugar
     */

    public static int guessResourceType(String URI) {

        int result = 0;
        InputStream in = null;

        // This is bullshit.
        if (URI == null || URI.length() == 0)
            return InputStreamSugar.BAD_URI;

        try {
            in = new FileInputStream(new File(URI));
            // It's a file
            result |= InputStreamSugar.FILE;
        } catch (Exception e) {
            // Not a file...
            URL u;
            try {
                u = new URL(URI);
            } catch (MalformedURLException e1) {
                return InputStreamSugar.BAD_URI;
            }
            try {
                in = u.openConnection().getInputStream();
                result |= InputStreamSugar.NETWORK_FILE;
            } catch (IOException e1) {
                return InputStreamSugar.BAD_URI;
            }

        }

        // Try guessing if it's a ZIP file. A bit lame, really
        // TODO: add proper validation, and maybe MIME type checking
        // for network streams, for cases that we can't really
        // tell from extension alone.

        if (checkForExtension(URI, "zip")) {
            result |= InputStreamSugar.ZIP_FILE;

        }

        try {
            in.close();
        } catch (IOException e) {

        }

        // All is well. Go on...
        return result;
    }

}

package utils;

/** Half-assed way of finding the OS we're running under, shamelessly 
 * ripped from:
 * 
 *  http://www.mkyong.com/java/how-to-detect-os-in-java-systemgetpropertyosname/
 * .
 * This is required, as some things in AWT don't work exactly consistently cross-OS
 * (AWT frame size is the first thing that goes wrong, but also mouse grabbing
 * behavior).
 * 
 * TODO: replace with Apache Commons library?
 *  
 * @author velktron
 *
 */

public class OSValidator{
 
	public static boolean isWindows(){
 
		String os = System.getProperty("os.name").toLowerCase();
		//windows
	    return (os.indexOf( "win" ) >= 0); 
 
	}
 
	public static boolean isMac(){
 
		String os = System.getProperty("os.name").toLowerCase();
		//Mac
	    return (os.indexOf( "mac" ) >= 0); 
 
	}
 
	public static boolean isUnix(){
 
		String os = System.getProperty("os.name").toLowerCase();
		//linux or unix
	    return (os.indexOf( "nix") >=0 || os.indexOf( "nux") >=0);
 
	}
	
	public static boolean isUnknown(){
		return (!isWindows() && !isUnix() && !isMac());
	}
}

package doom;

import defines.skill_t;

/** Groups functions formerly in d_game, 
 * in case you want to provide a different implementation 
 */

public interface IDoomGame {

	 void ExitLevel ();
	 void WorldDone ();

     boolean CheckDemoStatus();
     
     /** Can be called by the startup code or M_Responder.
     A normal game starts at map 1,
     but a warp test can start elsewhere */
     
     public void DeferedInitNew (skill_t skill, int episode, int map);
     
     /** Can be called by the startup code or M_Responder,
     calls P_SetupLevel or W_EnterWorld. */
   public void LoadGame (String name);

   /** Called by M_Responder. */
   public void SaveGame (int slot, String description);
   
   /** Takes a screenshot *NOW*
    * 
    */
   public void ScreenShot() ;
   
   public void StartTitle();
   
   public gameaction_t getGameAction();

   public void setGameAction(gameaction_t ga);
   
   // public void PlayerReborn(int player);
   
   void DeathMatchSpawnPlayer(int playernum);

}

package doom;

public interface NetConsts {

    public static int    NCMD_EXIT=      0x80000000;
    public static int    NCMD_RETRANSMIT     =0x40000000;
    public static int    NCMD_SETUP      =0x20000000;
    public static int   NCMD_KILL    =   0x10000000; // kill game
    public static int    NCMD_CHECKSUM   =   0x0fffffff;

    public static int  DOOMCOM_ID =     0x12345678;


    //Networking and tick handling related. Moved to DEFINES
    //protected static int    BACKUPTICS     = 12;


    // command_t
    public  static short CMD_SEND    = 1;
    public  static short CMD_GET = 2; 
    
}

package doom;

import n.DoomSystemNetworking;
import f.EndLevel;
import f.Finale;
import f.Wiper;
import hu.HU;
import i.IDiskDrawer;
import i.IDoomSystem;
import i.DoomVideoInterface;
import m.IDoomMenu;
import m.IRandom;
import m.IVariablesManager;
import p.AbstractLevelLoader;
import p.Actions;
import rr.ISpriteManager;
import rr.Renderer;
import rr.TextureManager;
import s.IDoomSound;
import s.IMusic;
import s.ISoundDriver;
import st.AbstractStatusBar;
import timing.ITicker;
import v.DoomVideoRenderer;
import w.IWadLoader;
import automap.IAutoMap;

/** Since a lot of stuff requires shared/global access to 
 *  the WadLoader, the Renderer, the Video system etc. and
 *  we're trying to depart from the global/static mentality,
 *  a common sharing is required. Ideally, this would be a perfect
 *  example of where multiple inheritance could be adopted, since most
 *  stuff needs to share this status anyway. The next best thing is
 *  to have local references of any used fields in the classes that use them.
 * 
 *  About generics: T refers to the type of the graphics resources, and is
 *  currently byte[], as all graphics resources are 8-bit indexed. There are
 *  no plans that this will change anytime soon. Some classes should allow 
 *  different types in theory, but it would be too complex and pointless to 
 *  make everything fully compliant at the moment.
 *  
 *  V refers to the type of DISPLAY, and can be 8-bit (byte[]), 16-bit (short[] 
 *  for HiColor and lesser modes such as ARGB4444, etc.), and, in the future, 
 *  int[] (truecolor).
 * 
 *  The general approach is sharing as much code as possible between different 
 *  implementations (e.g. rendering code), and only specialize methods/classes when
 *  the abstraction of generics isn't enough (typically, when you have to assign
 *  directly to primitive arrays or deal with primitive method signatures).
 *  
 *  Classes that have specialized code for indexed and hicolor modes should be top-level
 *  classes in their package, and contain two nested, static, extending classes called
 *  Indexed and HiColor e.g. new MyClass.Indexed() and new MyClass.HiColor(), while any common 
 *  code should reside in MyClass.
 * 
 * @author velktron
 *
 */

public class DoomContext<T,V>{
	
    public DoomMain<T,V> DM;
    public IDoomGame DG;
    public IWadLoader W;
    public IRandom RND;
    public IDoomSystem I;
    public IDoomSound S;
    public ISoundDriver ISND;
    public IMusic IMUS;
    public DoomVideoInterface<V> VI;
    public AbstractStatusBar ST;
    public DoomVideoRenderer<T,V> V;
    public DoomSystemNetworking DNI;
    public IDoomGameNetworking DGN;
    public AbstractLevelLoader LL;
    public IDoomMenu M;
    public Actions P;
    public Renderer<T,V> R;
    public HU HU;
    public IAutoMap<T,V> AM;
    public Finale<T> F;
    public EndLevel<T,V> WI;
    public Wiper<T,V> WIPE;
    public TextureManager<T> TM;
    public ISpriteManager SM;
    public ICommandLineManager CM;
    public ITicker TICK; 
    public IDiskDrawer DD;
    public IVariablesManager VM;
}

package doom;

import java.util.Hashtable;

import utils.C2JUtils;

import defines.GameMode_t;

public class DoomVersions {

	public final static Hashtable<String,GameMode_t> VersionChecker=new Hashtable<String,GameMode_t>();
	
	static {
		VersionChecker.put("doom.wad",GameMode_t.registered);
		VersionChecker.put("doom2.wad",GameMode_t.commercial);
		VersionChecker.put("udoom.wad",GameMode_t.retail);
		VersionChecker.put("tnt.wad",GameMode_t.pack_tnt);
		VersionChecker.put("plutonia.wad",GameMode_t.pack_plut);
		VersionChecker.put("doom1.wad",GameMode_t.shareware);
		VersionChecker.put("xbla.wad",GameMode_t.pack_xbla);
	}
	
	public DoomVersions(){
		
	}
	
	/** Try all versions in given doommwaddir
	 * 
	 */
	
	public void tryThemAll(String doomwaddir){
		 // Commercial.
        doom2wad = (doomwaddir+ "/doom2.wad");

        // Retail.
        doomuwad = (doomwaddir+ "/doomu.wad");    

        // Registered.
        doomwad = (doomwaddir+ "/doom.wad");

        // Shareware.
        doom1wad = (doomwaddir+ "/doom1.wad");

        // Bug, dear Shawn.
        // Insufficient malloc, caused spurious realloc errors.
        plutoniawad = (doomwaddir+ "/plutonia.wad");

        tntwad = (doomwaddir+ "/tnt.wad");

        xblawad = (doomwaddir+ "/xbla.wad");
        
        // French stuff.
        doom2fwad=(doomwaddir+ "/doom2f.wad");
	}
	
	public String 
	doom1wad,
    doomwad,
    doomuwad,
    doom2wad,
    doom2fwad,
    plutoniawad,    
    tntwad,
    xblawad;
	
	/** Try only one IWAD. 
	 * 
	 * @param iwad
	 * @return
	 */

	public GameMode_t tryOnlyOne(String iwad, String doomwaddir) {
		
		// Is it a known and valid version?
		GameMode_t tmp=VersionChecker.get(iwad.toLowerCase());
		if (tmp!=null) {
		// Can we read it?
		if (C2JUtils.testReadAccess(doomwaddir+iwad))
			return tmp; // Yes, so communicate the gamemode back.
		}
		
		// It's either invalid or we can't read it.
		// Fuck that.
		return null;
	}
	
	
}

package doom;

/** Meant to provide a more lightweight alternative to Java's serialization model,
 *  specifically for the purpose of sending
 *  Objects implementing this can return references to one same byte array, with minimal
 *  overhead. Since it's for send-only purposes, it won't matter if it's  modified.
 *   *  
 *  But don't use it in lieu of CacheableDoomObject! 
 * 
 * @author admin
 *
 */

public interface IDatagramSerializable {
    
        /** Packs object into a byte array suitable to send over 
         * datagram networks. Typically, objects cache this array
         * for later use, and is availabe through cached()
         * 
         * @return
         */
    
        public byte[] pack();
        
        /** Packs object into a byte array suitable to send over 
         * datagram networks. The array is supplied externally 
         * (good for daisy-chaining stuff into a single packet).
         * 
         * @return
         */
    
        public void pack(byte[] buf, int offset);
        
        /** Deserializes an object from a given byte buffer.
         *  Only the first (sizeof) bytes will be used, dependant
         *  on each object's implementation. Will NOT also copy
         *  the byte[] caches. 
         */
        
        public void unpack(byte[] buf);
        
        /** Deserializes an object from a given byte buffer.
         *  Only the first (sizeof) bytes will be used, starting
         *  from a specified offset, dependant on each object's 
         *  implementation.
         */
        public void unpack(byte[] buf, int offset);
        
        /** Only use this if you are 100% sure that the object's content
         *  won't have changed since the last call of pack(). 
         *
         * @return Should return the underlying byte[] array directly.
         */
        public byte[] cached();
       
}

package doom;

// Event structure.

public class event_t {
	
	public event_t(){
	}

	   public event_t(event_t t){
	        this.type = t.type;
	        this.data1 = t.data1;
	        this.data2 = t.data2;
	        this.data3 = t.data3;
	    }

	
    public event_t(evtype_t type, int data) {
        this.type = type;
        this.data1 = data;
    }

    public event_t(char c) {
        this.type = evtype_t.ev_keydown;
        this.data1 = c;
    }

    public event_t(evtype_t type, int data1, int data2, int data3) {
        this.type = type;
        this.data1 = data1;
        this.data2 = data2;
        this.data3 = data3;
    }
    
    public void setFrom(event_t t){
        this.type = t.type;
        this.data1 = t.data1;
        this.data2 = t.data2;
        this.data3 = t.data3;
    }

    public evtype_t type;

    /** keys / mouse/joystick buttons, or wheel rotation amount */
    public int data1;

    /** mouse/joystick x move */
    public int data2;

    /** mouse/joystick y move */
    public int data3;

};

package doom;

import static data.Defines.*;
import static g.Keys.*;
import static data.Limits.*;
import java.io.OutputStreamWriter;

import automap.IAutoMap;
import m.IUseVariables;
import m.IVariablesManager;
import m.Settings;
import p.mobj_t;
import rr.Renderer;
import utils.C2JUtils;
import v.DoomVideoRenderer;
import data.mapthing_t;
import defines.*;
import demo.IDoomDemo;
import f.Finale;
import f.Wiper;

/**
 * We need globally shared data structures, for defining the global state
 * variables. MAES: in pure OO style, this should be a global "Doom state"
 * object to be passed along various modules. No ugly globals here!!! Now, some
 * of the variables that appear here were actually defined in separate modules.
 * Pretty much, whatever needs to be shared with other modules was placed here,
 * either as a local definition, or as an extern share. The very least, I'll
 * document where everything is supposed to come from/reside.
 */

public abstract class DoomStatus<T,V> extends DoomContext<T,V> implements IUseVariables {

	public static final int	BGCOLOR=		7;
	public static final int	FGCOLOR		=8;
	public static int   RESENDCOUNT =10;
	public static int   PL_DRONE    =0x80;  // bit flag in doomdata->player

	public String[]		wadfiles=new String[MAXWADFILES];

	boolean         drone;
	
    /** Command line parametersm, actually defined in d_main.c */
    public boolean nomonsters; // checkparm of -nomonsters

    public boolean respawnparm; // checkparm of -respawn

    public boolean fastparm; // checkparm of -fast

    public boolean devparm; // DEBUG: launched with -devparm

 // MAES: declared as "extern", shared with Menu.java
    public  boolean	inhelpscreens;

    boolean		advancedemo;
    
    /////////// Local to doomstat.c ////////////
    // TODO: hide those behind getters
    
    /** Game Mode - identify IWAD as shareware, retail etc. 
     *  This is now hidden behind getters so some cases like plutonia
     *  etc. can be handled more cleanly.
     * */

    private GameMode_t gamemode;
    
    public void setGameMode(GameMode_t mode){
    	this.gamemode=mode;
    }
    
    public GameMode_t getGameMode(){
    	return gamemode;
    }
    
    public boolean isShareware(){
    	return (gamemode== GameMode_t.shareware);
    }    
    
    /** Commercial means Doom 2, Plutonia, TNT, and possibly others like XBLA.
     * 
     * @return
     */
    public boolean isCommercial(){
    	return (gamemode== GameMode_t.commercial ||
    			gamemode== GameMode_t.pack_plut ||
    			gamemode== GameMode_t.pack_tnt ||
    			gamemode== GameMode_t.pack_xbla);
    }
    
    /** Retail means Ultimate.
     * 
     * @return
     */
    public boolean isRetail(){
    	return (gamemode== GameMode_t.retail );
    }
    
    /** Registered is a subset of Ultimate 
     * 
     * @return
     */

    public boolean isRegistered(){
    	return (gamemode== GameMode_t.registered || gamemode== GameMode_t.retail );
    }
    
    public GameMission_t gamemission;

    /** Set if homebrew PWAD stuff has been added. */
    public boolean modifiedgame;

    /** Language. */
    public Language_t language;

    // /////////// Normally found in d_main.c ///////////////

    // Selected skill type, map etc.

    /** Defaults for menu, methinks. */
    public skill_t startskill;

    public int startepisode;

    public int startmap;

    public boolean autostart;

    /** Selected by user */
    public skill_t gameskill;

    public int gameepisode;

    public int gamemap;

    /** Nightmare mode flag, single player. */
    public boolean respawnmonsters;

    /** Netgame? Only true if >1 player. */
    public boolean netgame;

    /**
     * Flag: true only if started as net deathmatch. An enum might handle
     * altdeath/cooperative better. Use altdeath for the "2" value
     */
    public boolean deathmatch;

    /** Use this instead of "deathmatch=2" which is bullshit. */
    public boolean altdeath;
    
    //////////// STUFF SHARED WITH THE RENDERER ///////////////
    
    // -------------------------
    // Status flags for refresh.
    //

    public boolean nodrawers;

    public boolean noblit;
    
    public boolean viewactive;
    
    // Player taking events, and displaying.
    public int consoleplayer;

    public int displayplayer;
    
    // Depending on view size - no status bar?
    // Note that there is no way to disable the
    // status bar explicitely.
    public boolean statusbaractive;

    public boolean automapactive; // In AutoMap mode?

    public boolean menuactive; // Menu overlayed?

    public boolean paused; // Game Pause?

    // -------------------------
    // Internal parameters for sound rendering.
    // These have been taken from the DOS version,
    // but are not (yet) supported with Linux
    // (e.g. no sound volume adjustment with menu.

    // These are not used, but should be (menu).
    // From m_menu.c:
    // Sound FX volume has default, 0 - 15
    // Music volume has default, 0 - 15
    // These are multiplied by 8.
    /** maximum volume for sound */
    public int snd_SfxVolume;

    /** maximum volume for music */
    public int snd_MusicVolume;

    /** Maximum number of sound channels */
    public int numChannels;

    // Current music/sfx card - index useless
    // w/o a reference LUT in a sound module.
    // Ideally, this would use indices found
    // in: /usr/include/linux/soundcard.h
    public int snd_MusicDevice;

    public int snd_SfxDevice;

    // Config file? Same disclaimer as above.
    public int snd_DesiredMusicDevice;

    public int snd_DesiredSfxDevice;

    
    // -------------------------------------
    // Scores, rating.
    // Statistics on a given map, for intermission.
    //
    public int totalkills;

    public int totalitems;

    public int totalsecret;

    /** TNTHOM "cheat" for flashing HOM-detecting BG */
	public boolean flashing_hom;
    
    // Added for prBoom+ code
    public int totallive;
    
    // Timer, for scores.
    public int levelstarttic; // gametic at level start

    public int leveltime; // tics in game play for par

    // --------------------------------------
    // DEMO playback/recording related stuff.
    // No demo, there is a human player in charge?
    // Disable save/end game?
    public boolean usergame;

    // ?
    public boolean demoplayback;

    public boolean demorecording;

    // Quit after playing a demo from cmdline.
    public boolean singledemo;

    /** Set this to GS_DEMOSCREEN upon init, else it will be null*/
    public gamestate_t gamestate=gamestate_t.GS_DEMOSCREEN;

    // -----------------------------
    // Internal parameters, fixed.
    // These are set by the engine, and not changed
    // according to user inputs. Partly load from
    // WAD, partly set at startup time.

    public int gametic;

    // Bookkeeping on players - state.
    public player_t[] players;

    // Alive? Disconnected?
    public boolean[] playeringame = new boolean[MAXPLAYERS];

    public mapthing_t[] deathmatchstarts = new mapthing_t[MAX_DM_STARTS];

    /** pointer into deathmatchstarts */
    public int deathmatch_p;

    /** Player spawn spots. */
    public mapthing_t[] playerstarts = new mapthing_t[MAXPLAYERS];

    /** Intermission stats.
      Parameters for world map / intermission. */
    public wbstartstruct_t wminfo;

    /** LUT of ammunition limits for each kind.
        This doubles with BackPack powerup item.
        NOTE: this "maxammo" is treated like a global.
         */
    public final static int[] maxammo =  {200, 50, 300, 50};

    // -----------------------------------------
    // Internal parameters, used for engine.
    //

    // File handling stuff.
    
    public OutputStreamWriter debugfile;

    // if true, load all graphics at level load
    public boolean precache;

    // wipegamestate can be set to -1
    // to force a wipe on the next draw
    // wipegamestate can be set to -1 to force a wipe on the next draw
    public gamestate_t     wipegamestate = gamestate_t.GS_DEMOSCREEN;
    
    public int mouseSensitivity=15;
    
    // debug flag to cancel adaptiveness
    // Set to true during timedemos.
    public boolean singletics=false;
    
    /* A "fastdemo" is a demo with a clock that tics as
     * fast as possible, yet it maintains adaptiveness and doesn't
     * try to render everything at all costs.
     */
    protected boolean fastdemo;
    protected boolean normaldemo;
    
    protected String loaddemo;
    
    public int bodyqueslot;

    // Needed to store the number of the dummy sky flat.
    // Used for rendering,
    // as well as tracking projectiles etc.
    //public int skyflatnum;

    // TODO: Netgame stuff (buffers and pointers, i.e. indices).

    // TODO: This is ???
    public doomcom_t doomcom;

    // TODO: This points inside doomcom.
    public doomdata_t netbuffer;

    public ticcmd_t[] localcmds = new ticcmd_t[BACKUPTICS];

    public int rndindex;

    public int maketic;

    public int[] nettics = new int[MAXNETNODES];

    public ticcmd_t[][] netcmds;// [MAXPLAYERS][BACKUPTICS];
      
    /** MAES: this WAS NOT in the original. 
     *  Remember to call it!
     */
    protected void initNetGameStuff() {
        //this.netbuffer = new doomdata_t();
        this.doomcom = new doomcom_t();
        this.netcmds = new ticcmd_t[MAXPLAYERS][BACKUPTICS];

        C2JUtils.initArrayOfObjects(localcmds);
        for (int i=0;i<MAXPLAYERS;i++){
        C2JUtils.initArrayOfObjects(netcmds[i]);
        }
        
    }
    
    public abstract void Init();

    // Fields used for selecting variable BPP implementations.
    
    protected abstract Finale<T> selectFinale();
    
    protected abstract DoomVideoRenderer<T,V> selectVideoRenderer();
    
    protected abstract Renderer<T,V> selectRenderer();
    
    protected abstract Wiper<T,V> selectWiper();
    
    protected abstract IAutoMap<T,V> selectAutoMap();
    
    // MAES: Fields specific to DoomGame. A lot of them were
    // duplicated/externalized
    // in d_game.c and d_game.h, so it makes sense adopting a more unified
    // approach.
    protected gameaction_t gameaction=gameaction_t.ga_nothing;

    public boolean sendpause; // send a pause event next tic

    protected boolean sendsave; // send a save event next tic

    protected int starttime;

    protected boolean timingdemo; // if true, exit with report on completion

    public boolean getPaused() {
        return paused;
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
    }

    // ////////// DEMO SPECIFIC STUFF/////////////

    protected String demoname;

    protected boolean netdemo;

    //protected IDemoTicCmd[] demobuffer;

    protected IDoomDemo demobuffer;
    /** pointers */
    // USELESS protected int demo_p;

   // USELESS protected int demoend;

    protected short[][] consistancy = new short[MAXPLAYERS][BACKUPTICS];

    protected byte[] savebuffer;

    /* TODO Proper reconfigurable controls. Defaults hardcoded for now. T3h h4x, d00d. */

    public int key_right=KEY_RIGHTARROW;

    public int key_left=KEY_LEFTARROW;

    public int key_up='w';

    public int key_down='a';

    public int key_strafeleft='s';

    public int key_straferight='d';

    public int key_fire=KEY_CTRL;

    public int key_use=' ';
    
    public int key_strafe=KEY_ALT;

    public int key_speed=KEY_SHIFT;
    
    // Heretic stuff
    public int		key_lookup=KEY_PGUP;
    public int		key_lookdown=KEY_PGDN;
    public int      key_lookcenter=KEY_END;

    public int mousebfire=0;

    public int mousebstrafe=1;

    public int mousebforward=2;

    public int joybfire;

    public int joybstrafe;

    public int joybuse;

    public int joybspeed;
    
    /** Cancel vertical mouse movement by default */
    protected boolean novert=true;

    protected int MAXPLMOVE() {
        return forwardmove[1];
    }

    protected static final int TURBOTHRESHOLD = 0x32;

    /** fixed_t */
    protected final int[] forwardmove = { 0x19, 0x32 }; // + slow turn

    protected final int[] sidemove = { 0x18, 0x28 };

    protected final int[] angleturn = { 640, 1280, 320 };

    protected static final int SLOWTURNTICS = 6;

    protected static final int NUMKEYS = 256;

    protected boolean[] gamekeydown = new boolean[NUMKEYS];

    protected boolean keysCleared;
    
    public boolean alwaysrun;

    protected int turnheld; // for accelerative turning
    protected int lookheld; // for accelerative looking?

    protected boolean[] mousearray = new boolean[4];

    /** This is an alias for mousearray [1+i] */
    protected boolean mousebuttons(int i) {
        return mousearray[1 + i]; // allow [-1]
    }

    protected void mousebuttons(int i, boolean value) {
        mousearray[1 + i] = value; // allow [-1]
    }

    protected void mousebuttons(int i, int value) {
        mousearray[1 + i] = value != 0; // allow [-1]
    }

    /** mouse values are used once */
    protected int mousex, mousey;

    protected int dclicktime;

    protected int dclickstate;

    protected int dclicks;

    protected int dclicktime2, dclickstate2, dclicks2;

    /** joystick values are repeated */
    protected int joyxmove, joyymove;

    protected boolean[] joyarray = new boolean[5];

    protected boolean joybuttons(int i) {
        return joyarray[1 + i]; // allow [-1]
    }

    protected void joybuttons(int i, boolean value) {
        joyarray[1 + i] = value; // allow [-1]
    }

    protected void joybuttons(int i, int value) {
        joyarray[1 + i] = value != 0; // allow [-1]
    }

    protected int savegameslot;

    protected String savedescription;

    protected static final int BODYQUESIZE = 32;

    protected mobj_t[] bodyque = new mobj_t[BODYQUESIZE];

    public String statcopy; // for statistics driver

    
    
    /** Not documented/used in linuxdoom. I supposed it could be used to
     *  ignore mouse input?
     */
    
    public boolean use_mouse,use_joystick;
    
    
    /** More prBoom+ stuff. Used mostly for code uhm..reuse, rather
     *  than to actually change the way stuff works.
     *   
     */
    
    public static int compatibility_level;
    
    public DoomStatus(){
    	players = new player_t[MAXPLAYERS];
    	C2JUtils.initArrayOfObjects(players);

    	this.wminfo=new wbstartstruct_t();
    	initNetGameStuff();
    }

    @Override
    public void registerVariableManager(IVariablesManager manager) {
        this.VM=manager;        
    }

    @Override
    public void update() {

           this.snd_SfxVolume=VM.getSetting(Settings.sfx_volume).getInteger();
           this.snd_MusicVolume=VM.getSetting(Settings.music_volume).getInteger();
           this.alwaysrun=VM.getSetting(Settings.alwaysrun).getBoolean();
                     
          
           // Keys...
           this.key_right=VM.getSetting(Settings.key_right).getChar();
           this.key_left=VM.getSetting(Settings.key_left).getChar();
           this.key_up=VM.getSetting(Settings.key_up).getChar();
           this.key_down=VM.getSetting(Settings.key_down).getChar();
           this.key_strafeleft=VM.getSetting(Settings.key_strafeleft).getChar();
           this.key_straferight=VM.getSetting(Settings.key_straferight).getChar();
           this.key_fire=VM.getSetting(Settings.key_fire).getChar();
           this.key_use=VM.getSetting(Settings.key_use).getChar();
           this.key_strafe=VM.getSetting(Settings.key_strafe).getChar();
           this.key_speed=VM.getSetting(Settings.key_speed).getChar();
           

           // Mouse buttons
           this.use_mouse=VM.getSetting(Settings.use_mouse).getBoolean();
           this.mousebfire=VM.getSetting(Settings.mouseb_fire).getInteger();
           this.mousebstrafe=VM.getSetting(Settings.mouseb_strafe).getInteger();
           this.mousebforward=VM.getSetting(Settings.mouseb_forward).getInteger();
           
           // Joystick

           this.use_joystick=VM.getSetting(Settings.use_joystick).getBoolean();
           this.joybfire=VM.getSetting(Settings.joyb_fire).getInteger();
           this.joybstrafe=VM.getSetting(Settings.joyb_strafe).getInteger();
           this.joybuse=VM.getSetting(Settings.joyb_use).getInteger();
           this.joybspeed=VM.getSetting(Settings.joyb_speed).getInteger();

           // Sound
           this.numChannels=VM.getSetting(Settings.snd_channels).getInteger();

           // Video...so you should wait until video renderer is active.           
           this.V.setUsegamma(VM.getSetting(Settings.usegamma).getInteger());
           
           // These should really be handled by the menu.
           this.M.setShowMessages(VM.getSetting(Settings.show_messages).getBoolean());
           this.M.setScreenBlocks(VM.getSetting(Settings.screenblocks).getInteger());

           // These should be handled by the HU

           for (int i=0;i<=9;i++){
               
           String chatmacro=String.format("chatmacro%d",i);
           this.HU.setChatMacro(i,VM.getSetting(chatmacro).toString());
           }
        }

    @Override
    public void commit() {
        VM.putSetting(Settings.sfx_volume,this.snd_SfxVolume);
        VM.putSetting(Settings.music_volume,this.snd_MusicVolume);
        VM.putSetting(Settings.alwaysrun, this.alwaysrun);
       
       
        // Keys...
        VM.putSetting(Settings.key_right,this.key_right);
        VM.putSetting(Settings.key_left,this.key_left);
        VM.putSetting(Settings.key_up,this.key_up);
        VM.putSetting(Settings.key_down,this.key_down);
        VM.putSetting(Settings.key_strafeleft,this.key_strafeleft);
        VM.putSetting(Settings.key_straferight,this.key_straferight);
        VM.putSetting(Settings.key_fire,this.key_fire);
        VM.putSetting(Settings.key_use,this.key_use);
        VM.putSetting(Settings.key_strafe,this.key_strafe);
        VM.putSetting(Settings.key_speed,this.key_speed);
        

        // Mouse buttons
        VM.putSetting(Settings.use_mouse,this.use_mouse);
        VM.putSetting(Settings.mouseb_fire,this.mousebfire);
        VM.putSetting(Settings.mouseb_strafe,this.mousebstrafe);
        VM.putSetting(Settings.mouseb_forward,this.mousebforward);
        
        // Joystick

        VM.putSetting(Settings.use_joystick,this.use_joystick);
        VM.putSetting(Settings.joyb_fire,this.joybfire);
        VM.putSetting(Settings.joyb_strafe,this.joybstrafe);
        VM.putSetting(Settings.joyb_use,this.joybuse);
        VM.putSetting(Settings.joyb_speed,this.joybspeed);

        // Sound
        VM.putSetting(Settings.snd_channels,this.numChannels);
        
        // Video...         
        VM.putSetting(Settings.usegamma,V.getUsegamma());
        
        // These should really be handled by the menu.
        VM.putSetting(Settings.show_messages,this.M.getShowMessages());
        VM.putSetting(Settings.screenblocks,this.M.getScreenBlocks());
        
        // These should be handled by the HU

        for (int i=0;i<=9;i++){
            
        String chatmacro=String.format("chatmacro%d",i);
        VM.putSetting(chatmacro,this.HU.chat_macros[i]);
        }
        
    }
    

    

}

// $Log: DoomStatus.java,v $
// Revision 1.36  2012/11/06 16:04:58  velktron
// Variables manager less tightly integrated.
//
// Revision 1.35  2012/09/24 17:16:22  velktron
// Massive merge between HiColor and HEAD. There's no difference from now on, and development continues on HEAD.
//
// Revision 1.34.2.3  2012/09/24 16:58:06  velktron
// TrueColor, Generics.
//
// Revision 1.34.2.2  2012/09/20 14:25:13  velktron
// Unified DOOM!!!
//
// Revision 1.34.2.1  2012/09/17 16:06:52  velktron
// Now handling updates of all variables, though those specific to some subsystems should probably be moved???
//
// Revision 1.34  2011/11/01 23:48:10  velktron
// Added tnthom stuff.
//
// Revision 1.33  2011/10/24 02:11:27  velktron
// Stream compliancy
//
// Revision 1.32  2011/10/07 16:01:16  velktron
// Added freelook stuff, using Keys.
//
// Revision 1.31  2011/09/27 16:01:41  velktron
// -complevel_t
//
// Revision 1.30  2011/09/27 15:54:51  velktron
// Added some more prBoom+ stuff.
//
// Revision 1.29  2011/07/28 17:07:04  velktron
// Added always run hack.
//
// Revision 1.28  2011/07/16 10:57:50  velktron
// Merged finnw's changes for enabling polling of ?_LOCK keys.
//
// Revision 1.27  2011/06/14 20:59:47  velktron
// Channel settings now read from default.cfg. Changes in sound creation order.
//
// Revision 1.26  2011/06/04 11:04:25  velktron
// Fixed registered/ultimate identification.
//
// Revision 1.25  2011/06/01 17:35:56  velktron
// Techdemo v1.4a level. Default novert and experimental mochaevents interface.
//
// Revision 1.24  2011/06/01 00:37:58  velktron
// Changed default keys to WASD.
//
// Revision 1.23  2011/05/31 21:45:51  velktron
// Added XBLA version as explicitly supported.
//
// Revision 1.22  2011/05/30 15:50:42  velktron
// Changed to work with new Abstract classes
//
// Revision 1.21  2011/05/26 17:52:11  velktron
// Now using ICommandLineManager
//
// Revision 1.20  2011/05/26 13:39:52  velktron
// Now using ICommandLineManager
//
// Revision 1.19  2011/05/25 17:56:52  velktron
// Introduced some fixes for mousebuttons etc.
//
// Revision 1.18  2011/05/24 17:44:37  velktron
// usemouse added for defaults
//
package doom;

import i.DiskDrawer;
import i.DoomStatusAware;
import i.DoomSystem;
import i.DoomVideoInterface;
import i.Strings;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import n.DummyNetworkDriver;
import static data.dstrings.*;
import p.Actions;
import p.BoomLevelLoader;
import p.mobj_t;
import automap.IAutoMap;
import automap.Map;
import awt.AWTDoom;
import f.EndLevel;
import f.Finale;
import f.Wiper;
import hu.HU;
import m.Menu;
import m.MenuMisc;
import m.DoomRandom;
import m.Settings;
import m.VarsManager;
import static doom.NetConsts.*;
import static doom.englsh.*;
import data.Tables;
import data.dstrings;
import data.mapthing_t;
import data.mobjtype_t;
import defines.*;
import demo.IDemoTicCmd;
import demo.IDoomDemo;
import demo.VanillaDoomDemo;
import demo.VanillaTiccmd;
import data.sounds.musicenum_t;
import data.sounds.sfxenum_t;
import static data.Defines.BACKUPTICS;
import static g.Keys.*;
import static data.Defines.NORMALUNIX;
import static data.Defines.PU_STATIC;
import static data.Defines.VERSION;
import rr.Renderer;
import rr.SimpleTextureManager;
import rr.SpriteManager;
import rr.UnifiedRenderer;
import rr.ViewVars;
import rr.subsector_t;
import rr.parallel.ParallelRenderer;
import rr.parallel.ParallelRenderer2;
import s.AbstractDoomAudio;
import s.ClassicDoomSoundDriver;
import s.ClipSFXModule;
import s.DavidMusicModule;
import s.DavidSFXModule;
import s.DummyMusic;
import s.DummySFX;
import s.DummySoundDriver;
import s.SpeakerDoomSoundDriver;
import s.SuperDoomSoundDriver;
//import s.SpeakerDoomSoundDriver;

import savegame.IDoomSaveGame;
import savegame.IDoomSaveGameHeader;
import savegame.VanillaDSG;
import savegame.VanillaDSGHeader;
import st.StatusBar;
import timing.FastTicker;
import timing.ITicker;
import timing.MilliTicker;
import timing.NanoTicker;
import utils.C2JUtils;
import v.BufferedRenderer;
import v.BufferedRenderer16;
import v.BufferedRenderer32;
import v.ColorTint;
import v.DoomVideoRenderer;
import v.GammaTables;
import v.IVideoScale;
import v.IVideoScaleAware;
import v.PaletteGenerator;
//import v.VideoScaleInfo;
import v.VisualSettings;
import w.DoomBuffer;
import w.WadLoader;
import static data.Defines.*;
import static data.Limits.*;
import static data.Tables.*;
import static data.dstrings.SAVEGAMENAME;
import static data.info.mobjinfo;
import static data.info.states;
import static m.fixed_t.FRACBITS;
import static m.fixed_t.MAPFRACUNIT;
import static utils.C2JUtils.*;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: DoomMain.java,v 1.110 2016/06/06 22:21:24 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//	DOOM main program (D_DoomMain) and game loop (D_DoomLoop),
//	plus functions to determine game mode (shareware, registered),
//	parse command line parameters, configure game parameters (turbo),
//	and call the startup functions.
//
//  In Mocha Doom, this was unified with d_game and doomstat.c
//
//-----------------------------------------------------------------------------

public abstract class DoomMain<T,V> extends DoomStatus<T,V> implements IDoomGameNetworking, IDoomGame, IDoom, IVideoScaleAware{

    public static final String rcsid = "$Id: DoomMain.java,v 1.110 2016/06/06 22:21:24 velktron Exp $";

    //
    // EVENT HANDLING
    //
    // Events are asynchronous inputs generally generated by the game user.
    // Events can be discarded if no responder claims them
    //
    public event_t[]         events=new event_t[MAXEVENTS];
    public int             eventhead;
    public int 		eventtail;

    /**
     * D_PostEvent
     * Called by the I/O functions when input is detected
     */

    public void PostEvent (event_t ev)
    {
        // TODO create a pool of reusable messages?
        // NEVERMIND we can use the original system.
        events[eventhead].setFrom(ev);
        eventhead = (++eventhead)&(MAXEVENTS-1);
    }


    /**
     * D_ProcessEvents
     * Send all the events of the given timestamp down the responder chain
     */ 
    public void ProcessEvents ()
    {
        event_t	ev;

        // IF STORE DEMO, DO NOT ACCEPT INPUT

        if ( ( isCommercial() )
                && (W.CheckNumForName("MAP01")<0) )
            return; 

        for ( ; eventtail != eventhead ; eventtail = (++eventtail)&(MAXEVENTS-1) )
        {
            ev = events[eventtail];
            if (M.Responder (ev)){
                //epool.checkIn(ev);
                continue;               // menu ate the event
            }
            Responder (ev);
            // We're done with it, return it to the pool.
            //epool.checkIn(ev);
        }
    }

    // "static" to Display, don't move.
    private  boolean		viewactivestate = false;
    private  boolean		menuactivestate = false;
    private  boolean		inhelpscreensstate = false;
    private  boolean		fullscreen = false;
    private  gamestate_t	oldgamestate = gamestate_t.GS_MINUS_ONE;
    private  int			borderdrawcount;

    /**
     * D_Display
     * draw current display, possibly wiping it from the previous
     * @throws IOException 
     */

    public void Display () throws IOException
    {
        int				nowtime;
        int				tics;
        int				wipestart;
        int				y;
        boolean			done;
        boolean			wipe;
        boolean			redrawsbar;

        if (nodrawers)
            return;                    // for comparative timing / profiling

        redrawsbar = false;

        // change the view size if needed
        if (R.getSetSizeNeeded())
        {
            R.ExecuteSetViewSize ();
            oldgamestate = gamestate_t.GS_MINUS_ONE;                      // force background redraw
            borderdrawcount = 3;
        }

        // save the current screen if about to wipe
        if (wipe=(gamestate != wipegamestate))
        {
            wipe = true;
            WIPE.StartScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);
        }
        else
            wipe = false;

        if (gamestate == gamestate_t.GS_LEVEL && eval(gametic))
            HU.Erase();

        // do buffered drawing
        switch (gamestate)
        {
        case GS_LEVEL:
            if (!eval(gametic))
                break;
            if (automapactive)
                AM.Drawer ();
            if (wipe || (!R.isFullHeight() && fullscreen) ||
            		(inhelpscreensstate && !inhelpscreens)
            		|| (DD.justDoneReading()))
                redrawsbar = true; // just put away the help screen
            ST.Drawer (R.isFullHeight(), redrawsbar );
            fullscreen = R.isFullHeight();
            break;

        case GS_INTERMISSION:
            WI.Drawer ();
            break;

        case GS_FINALE:
            F.Drawer ();
            break;

        case GS_DEMOSCREEN:
            PageDrawer ();
            break;
        }

        // draw the view directly
        if (gamestate == gamestate_t.GS_LEVEL && !automapactive && eval(gametic)){
        	if (flashing_hom){
                V.FillRect(gametic%256,0,view.getViewWindowX(),view.getViewWindowY(),
                    view.getScaledViewWidth(),view.getScaledViewHeight());
        	    }
            R.RenderPlayerView (players[displayplayer]);
        	}

        // Automap was active, update only HU.    
        if (gamestate == gamestate_t.GS_LEVEL && eval(gametic))
            HU.Drawer ();

        // clean up border stuff
        if (gamestate != oldgamestate && gamestate != gamestate_t.GS_LEVEL)
            VI.SetPalette (0);

        // see if the border needs to be initially drawn
        if (gamestate == gamestate_t.GS_LEVEL && oldgamestate != gamestate_t.GS_LEVEL)
        {
            viewactivestate = false;        // view was not active
            R.FillBackScreen ();    // draw the pattern into the back screen
        }

        // see if the border needs to be updated to the screen
        if (gamestate == gamestate_t.GS_LEVEL && !automapactive && !R.isFullScreen())
        {
            if (menuactive || menuactivestate || !viewactivestate)
                borderdrawcount = 3;
            if (eval(borderdrawcount))
            {
                R.DrawViewBorder ();    // erase old menu stuff
                borderdrawcount--;
            }

        }

        menuactivestate = menuactive;
        viewactivestate = viewactive;
        inhelpscreensstate = inhelpscreens;
        oldgamestate = wipegamestate = gamestate;

        // draw pause pic
        if (paused)
        {
            if (automapactive)
                y = 4;
            else
                y = view.getViewWindowY()+4;
            V.DrawPatchDirect(view.getViewWindowX()+(view.getScaledViewWidth()-68)/2,
                y,0,W.CachePatchName ("M_PAUSE", PU_CACHE));
        }


        // menus go directly to the screen
        M.Drawer ();          // menu is drawn even on top of everything
        NetUpdate ();         // send out any new accumulation

        // Disk access goes after everything.
        DD.Drawer();
        
        // normal update
        if (!wipe)
        {
            //System.out.print("Tick "+DM.gametic+"\t");
            //System.out.print(DM.players[0]);
            VI.FinishUpdate ();              // page flip or blit buffer
            return;
        }

        // wipe update. At this point, AT LEAST one frame of the game must have been
        // rendered for this to work. 22/5/2011: Fixed a vexing bug with the wiper.
        // Jesus Christ with a Super Shotgun!
        WIPE.EndScreen(0, 0, SCREENWIDTH, SCREENHEIGHT);

        wipestart = TICK.GetTime () - 1;

        do
        {
            do
            {
                nowtime = TICK.GetTime ();
                tics = nowtime - wipestart;
            } while (tics==0); // Wait until a single tic has passed.
            wipestart = nowtime;
            done = WIPE.ScreenWipe(Wiper.wipe.Melt.ordinal()
                , 0, 0, SCREENWIDTH, SCREENHEIGHT, tics);
            ISND.UpdateSound();
            ISND.SubmitSound();             // update sounds after one wipe tic.
            VI.UpdateNoBlit ();
            M.Drawer ();                    // menu is drawn even on top of wipes
            VI.FinishUpdate ();             // page flip or blit buffer
        } while (!done);

    }



    /**
     * D-DoomLoop()
     * Not a globally visible function,
     *  just included for source reference,
     *  called by D_DoomMain, never exits.
     * Manages timing and IO,
     *  calls all ?_Responder, ?_Ticker, and ?_Drawer,
     *  calls I_GetTime, I_StartFrame, and I_StartTic
     * @throws IOException 
     */

    public void DoomLoop () throws IOException
    {
        if (demorecording)
            BeginRecording ();

        if (eval(CM.CheckParm ("-debugfile")))
        {
            String    filename="debug"+consoleplayer+".txt";
            System.out.println("debug output to: "+filename);
            try {
                debugfile = new OutputStreamWriter(new FileOutputStream(filename));
            } catch (FileNotFoundException e) {
                System.err.println("Couldn't open debugfile. Now, that sucks some putrid shit out of John Romero's asshole!");
                e.printStackTrace();
            }
        }
        
        view=R.getView();
        
        while (true)
        {
            // frame syncronous IO operations
            VI.StartFrame ();                

            // process one or more tics
            if (singletics)
            {
                VI.StartTic ();
                ProcessEvents ();
                BuildTiccmd (netcmds[consoleplayer][maketic%BACKUPTICS]);
                if (advancedemo)
                    DoAdvanceDemo ();
                M.Ticker ();
                Ticker ();
                gametic++;
                maketic++;
            }
            else
            {
                DGN.TryRunTics (); // will run at least one tic (in NET)

            }

            S.UpdateSounds (players[consoleplayer].mo);// move positional sounds

            // Update display, next frame, with current state.
            Display ();
            
//#ifndef SNDSERV
	// Sound mixing for the buffer is snychronous.
	ISND.UpdateSound();
//#endif	
	// Synchronous sound output is explicitly called.
//#ifndef SNDINTR
	// Update sound output.
	ISND.SubmitSound();
//#endif
             
        }
    }
    
    // To keep an "eye" on the renderer.
    protected ViewVars view;

    //
    //  DEMO LOOP
    //
    int             demosequence;
    int             pagetic;
    String pagename;


    /**
     * D_PageTicker
     * Handles timing for warped projection
     */
    public final void PageTicker ()
    {
        if (--pagetic < 0)
            AdvanceDemo ();
    }



    /**
     * D_PageDrawer
     */

    public final void PageDrawer ()
    {

        // FIXME: this check wasn't necessary in vanilla, since pagename was 
        // guaranteed(?) not to be null or had a safe default value.  
        if (pagename != null)
            V.DrawPatchSolidScaled (0,0, SAFE_SCALE, SAFE_SCALE,0,W.CachePatchName(pagename, PU_CACHE));
    }


    /**
     * D_AdvanceDemo
     * Called after each demo or intro demosequence finishes
     */

    public void AdvanceDemo ()
    {
        advancedemo = true;
    }


    //
    // This cycles through the demo sequences.
    // FIXME - version dependant demo numbers?
    //
    public void DoAdvanceDemo ()
    {
        players[consoleplayer].playerstate = PST_LIVE;  // not reborn
        advancedemo = false;
        usergame = false;               // no save / end game here
        paused = false;
        gameaction = gameaction_t.ga_nothing;
        
        if ( isRetail()) // Allows access to a 4th demo.
            demosequence = (demosequence+1)%7;
        else
            demosequence = (demosequence+1)%6;

        switch (demosequence)
        {
        case 0:
            if ( isCommercial() )
                pagetic = 35 * 11;
            else
                pagetic = 170;
            gamestate = gamestate_t.GS_DEMOSCREEN;
            
            
            if (W.CheckNumForName("TITLEPIC")!=-1){
                pagename = "TITLEPIC";    
            } else {
                if (W.CheckNumForName("DMENUPIC")!=-1){
                    pagename = "DMENUPIC";
                }
            }
            
            if ( isCommercial() )
                S.StartMusic(musicenum_t.mus_dm2ttl);

            else
                S.StartMusic (musicenum_t.mus_intro); 
            break;
        case 1:
            DeferedPlayDemo ("demo1");
            break;
        case 2:
            pagetic = 200;
            gamestate = gamestate_t.GS_DEMOSCREEN;
            pagename = "CREDIT";
            break;
        case 3:
            DeferedPlayDemo ("demo2");
            break;
        case 4:
            gamestate = gamestate_t.GS_DEMOSCREEN;
            if ( isCommercial())
            {
                pagetic = 35 * 11;
                pagename = "TITLEPIC";
                S.StartMusic(musicenum_t.mus_dm2ttl);
            }
            else
            {
                pagetic = 200;

                if ( isRetail() )
                    pagename = "CREDIT";
                else
                    pagename = "HELP1";
            }
            break;
        case 5:
            DeferedPlayDemo ("demo3");
            break;
            // THE DEFINITIVE DOOM Special Edition demo
        case 6:
            DeferedPlayDemo ("demo4");
            break;
        }
    }



    /**
     * D_StartTitle
     */

    public void StartTitle ()
    {
        gameaction = gameaction_t.ga_nothing;
        demosequence = -1;
        AdvanceDemo ();
    }




    //      printtitle for every printed line
    StringBuffer            title=new StringBuffer();



    /**
     * D_AddFile
     * 
     * Adds file to the end of the wadfiles[] list.
     * Quite crude, we could use a listarray instead.
     * 
     * @param file
     */
    void AddFile (String file)
    {
        int     numwadfiles;
        String newfile;

        for (numwadfiles = 0 ; eval(wadfiles[numwadfiles]) ; numwadfiles++)
            ;

        newfile = new String(file);

        wadfiles[numwadfiles] = newfile;
    }
    

    /**
     * IdentifyVersion
     * Checks availability of IWAD files by name,
     * to determine whether registered/commercial features
     * should be executed (notably loading PWAD's).
     */

    public String IdentifyVersion ()
    {

        String home;
        String doomwaddir;
        DoomVersions vcheck=new DoomVersions();
        
        // By default.
        language=Language_t.english;
        
        // First, check for -iwad parameter.
        // If valid, then it trumps all others.
        
        int p;
        p=CM.CheckParm("-iwad");
        if (eval(p))
        {
        	System.out.println("-iwad specified. Will be used with priority\n");
            String test=CM.getArgv(p+1);
            
            // It might be quoted.
            test=C2JUtils.unquoteIfQuoted(test,'"');
            
            String separator=System.getProperty("file.separator");
            doomwaddir=test.substring(0, 1+test.lastIndexOf(separator));
            String iwad=test.substring( 1+test.lastIndexOf(separator));
            GameMode_t attempt=vcheck.tryOnlyOne(iwad,doomwaddir);
            // Note: at this point we can't distinguish between "doom" retail
            // and "doom" ultimate yet.
            if (attempt!=null) {
            	AddFile(doomwaddir+iwad);
            	this.setGameMode(attempt);
            	return (doomwaddir+iwad);
            }
        } else {
        // Unix-like checking. Might come in handy sometimes.   
        // This should ALWAYS be activated, else doomwaddir etc. won't be defined.

        doomwaddir = System.getenv("DOOMWADDIR");
        if (doomwaddir!=null){
                System.out.println("DOOMWADDIR found. Will be used with priority\n");
        }
        
        home = System.getenv("HOME");
        if (NORMALUNIX){
            if (!eval(home))
                I.Error("Please set $HOME to your home directory");
        }
        
        Settings.basedefault=home+"/.doomrc";   

        // None found, using current.
        if (!eval(doomwaddir))
            doomwaddir = ".";
    
        	vcheck.tryThemAll(doomwaddir);
        }

        // MAES: Interesting. I didn't know of that :-o
        if (eval(CM.CheckParm ("-shdev")))
        {
            setGameMode(GameMode_t.shareware);
            devparm = true;
            AddFile (dstrings.DEVDATA+"doom1.wad");
            AddFile (dstrings.DEVMAPS+"data_se/texture1.lmp");
            AddFile (dstrings.DEVMAPS+"data_se/pnames.lmp");
            Settings.basedefault=dstrings.DEVDATA+"default.cfg";
            return (dstrings.DEVDATA+"doom1.wad");
        }

        if (eval(CM.CheckParm ("-regdev")))
        {
            setGameMode(GameMode_t.registered);
            devparm = true;
            AddFile (dstrings.DEVDATA+"doom.wad");
            AddFile (dstrings.DEVMAPS+"data_se/texture1.lmp");
            AddFile (dstrings.DEVMAPS+"data_se/texture2.lmp");
            AddFile (dstrings.DEVMAPS+"data_se/pnames.lmp");
            Settings.basedefault=dstrings.DEVDATA+"default.cfg";
            return (dstrings.DEVDATA+"doom.wad");
        }

        if (eval(CM.CheckParm ("-comdev")))
        {
            setGameMode(GameMode_t.commercial);
            devparm = true;
            /* I don't bother
	if(plutonia)
	    D_AddFile (DEVDATA"plutonia.wad");
	else if(tnt)
	    D_AddFile (DEVDATA"tnt.wad");
	else*/

            AddFile (dstrings.DEVDATA+"doom2.wad");	    
            AddFile (dstrings.DEVMAPS+"cdata/texture1.lmp");
            AddFile (dstrings.DEVMAPS+"cdata/pnames.lmp");
            Settings.basedefault=dstrings.DEVDATA+"default.cfg";
            return (dstrings.DEVDATA+"doom2.wad");
        }


        if ( testReadAccess(vcheck.doom2fwad))
        {
            setGameMode(GameMode_t.commercial);
            // C'est ridicule!
            // Let's handle languages in config files, okay?
            language = Language_t.french;
            System.out.println("French version\n");
            AddFile (vcheck.doom2fwad);
            return vcheck.doom2fwad;
        }


        if ( testReadAccess(vcheck.doom2wad))
        {
            setGameMode(GameMode_t.commercial);
            AddFile (vcheck.doom2wad);
            return vcheck.doom2wad;
        }

        if ( testReadAccess (vcheck.plutoniawad) )
        {
            setGameMode(GameMode_t.pack_plut);
            AddFile (vcheck.plutoniawad);
            return vcheck.plutoniawad;
        }

        if ( testReadAccess ( vcheck.tntwad) )
        {
            setGameMode(GameMode_t.pack_tnt);
            AddFile (vcheck.tntwad);
            return vcheck.tntwad;
        }
        
        if ( testReadAccess ( vcheck.tntwad) )
        {
            setGameMode(GameMode_t.pack_xbla);
            AddFile (vcheck.xblawad);
            return vcheck.xblawad;
        }

        if ( testReadAccess (vcheck.doomuwad) )
        {
            // TODO auto-detect ultimate Doom even from doom.wad
        	// Maes: this is done later on.
            setGameMode(GameMode_t.retail);
            AddFile (vcheck.doomuwad);
            return vcheck.doomuwad;
        }

        if ( testReadAccess (vcheck.doomwad) )
        {
            setGameMode(GameMode_t.registered);
            AddFile (vcheck.doomwad);
            return vcheck.doomwad;
        }

        if ( testReadAccess (vcheck.doom1wad) )
        {
            setGameMode(GameMode_t.shareware);
            AddFile (vcheck.doom1wad);
            return vcheck.doom1wad;
        }

        // MAES: Maybe we should add FreeDoom here later.

        System.out.println("Game mode indeterminate.\n");
        setGameMode(GameMode_t.indetermined);

        return null;
        // We don't abort. Let's see what the PWAD contains.
        //exit(1);
        //I_Error ("Game mode indeterminate\n");
    }




    /**
     * D_DoomMain
     *
     * Completes the job started by Init, which only created the
     * instances of the various stuff and registered the "status aware" 
     * stuff. Here everything priority-critical is 
     * called and created in more detail.
     *
     *
     */

	public void Start() throws IOException
    {
        int             p;
        StringBuffer file=new StringBuffer();

        // TODO: This may modify the command line by appending more stuff
        // from an external file. Since it can affect other stuff too,
        // maybe it should be outside of Start() and into i.Main ?
        CM.FindResponseFile ();

        String iwadfilename=IdentifyVersion ();
        
        // Sets unbuffered output in C. Not needed here. setbuf (stdout, NULL);
        modifiedgame = false;

        nomonsters = eval(CM.CheckParm ("-nomonsters"));
        respawnparm = eval(CM.CheckParm ("-respawn"));
        fastparm = eval(CM.CheckParm ("-fast"));
        devparm = eval(CM.CheckParm ("-devparm"));
        if (eval(CM.CheckParm ("-altdeath")))
            //deathmatch = 2;
            altdeath=true;
        else if (eval(CM.CheckParm ("-deathmatch")))
            deathmatch = true;

        // MAES: Check for Ultimate Doom in "doom.wad" filename.
        WadLoader tmpwad=new WadLoader();
        try {
			tmpwad.InitFile(iwadfilename,true);
		} catch (Exception e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		// Check using a reloadable hack.
        CheckForUltimateDoom(tmpwad);    
       
        // MAES: better extract a method for this.
        GenerateTitle();

        // Print ticker info. It has already been set at Init() though.
        if (eval(CM.CheckParm("-millis"))){
            System.out.println("ITicker: Using millisecond accuracy timer.");
        } else if (eval(CM.CheckParm("-fasttic"))){
                System.out.println("ITicker: Using fastest possible timer.");
            }
        else {
            System.out.println("ITicker: Using nanosecond accuracy timer.");
        }

        System.out.println(title.toString());

        if (devparm)
            System.out.println(D_DEVSTR);

        // Running from CDROM?
        if (eval(CM.CheckParm("-cdrom")))
        {
            System.out.println(D_CDROM);
            //System.get("c:\\doomdata",0);
            System.out.println (Settings.basedefault+"c:/doomdata/default.cfg");
        }	

        // turbo option
        if ( eval(p=CM.CheckParm ("-turbo")) )
        {
            int     scale = 200;
            //int forwardmove[2];
            // int sidemove[2];

            if (p<CM.getArgc()-1)
                scale = Integer.parseInt(CM.getArgv(p+1));
            if (scale < 10)
                scale = 10;
            if (scale > 400)
                scale = 400;
            System.out.println("turbo scale: "+scale);
            forwardmove[0] = forwardmove[0]*scale/100;
            forwardmove[1] = forwardmove[1]*scale/100;
            sidemove[0] = sidemove[0]*scale/100;
            sidemove[1] = sidemove[1]*scale/100;
        }

        // add any files specified on the command line with -file wadfile
        // to the wad list
        //
        // convenience hack to allow -wart e m to add a wad file
        // prepend a tilde to the filename so wadfile will be reloadable
        p = CM.CheckParm ("-wart");
        if (eval(p))
        {
            char[] tmp=CM.getArgv(p).toCharArray();
            tmp[4]= 'p';// big hack, change to -warp
            CM.setArgv(p,new String(tmp));    
            GameMode_t gamemode=getGameMode();
            // Map name handling.
            switch (gamemode )
            {
            case shareware:
            case retail:
            case registered:
                file.append("~");
                file.append(DEVMAPS);
                file.append(String.format("E%cM%c.wad", CM.getArgv(p+1), CM.getArgv(p+2)));
                file.append(String.format("Warping to Episode %s, Map %s.\n",
                    CM.getArgv(p+1),CM.getArgv(p+2)));
                break;

            case commercial:
            default:
                p = Integer.parseInt(CM.getArgv(p+1));
                if (p<10){
                    file.append("~");
                    file.append(DEVMAPS);
                    file.append(String.format("cdata/map0%d.wad", p));
                }
                else
                {
                    file.append("~");
                    file.append(DEVMAPS);
                    file.append(String.format("cdata/map%d.wad", p));
                }
                break;
            }
            AddFile (file.toString());
        }

        p = CM.CheckParm ("-file");
        if (eval(p))
        {
            // the parms after p are wadfile/lump names,
            // until end of parms or another - preceded parm
            modifiedgame = true;            // homebrew levels
            // MAES 1/6/2011: Avoid + to avoid clashing with +map
            while (++p != CM.getArgc() && CM.getArgv(p).charAt(0) != '-' && CM.getArgv(p).charAt(0) != '+')
                AddFile (C2JUtils.unquoteIfQuoted(CM.getArgv(p),'"'));
        }
        
        p = CM.CheckParm ("-playdemo");
                
        if (eval(p)) normaldemo=true;
        else {
            p=CM.CheckParm ("-fastdemo");        
            if (eval(p)){
            System.out.println("Fastdemo mode. Boundless clock!");
            fastdemo=true;
            this.TICK=new FastTicker();            
            }
            else        
                if (!eval(p)) {
                    p = CM.CheckParm ("-timedemo");
                    if (eval(p)) singletics=true;
                }
        }

        // If any of the previous succeeded, try grabbing the filename.
        if ((normaldemo||fastdemo||singletics) && p < CM.getArgc()-1)
        {   
            loaddemo=CM.getArgv(p+1);
            AddFile (loaddemo+".lmp");
            System.out.printf("Playing demo %s.lmp.\n",loaddemo);
            autostart=true;
        }
        
        // Subsequent uses of loaddemo use only the lump name.
        loaddemo=C2JUtils.extractFileBase(loaddemo,0,true);

        // get skill / episode / map from parms
        // FIXME: should get them FROM THE DEMO itself.
        startskill = skill_t.sk_medium;
        startepisode = 1;
        startmap = 1;
        //autostart = false;


        p = CM.CheckParm ("-novert");
        if (eval(p) && p < CM.getArgc()-1)
        {
            novert=!(CM.getArgv(p+1).toLowerCase().compareTo("disable")==0);
            if (!novert) System.out.println("-novert ENABLED (default)");
            else System.out.println("-novert DISABLED. Hope you know what you're doing...");
        }

        p = CM.CheckParm ("-skill");
        if (eval(p) && p < CM.getArgc()-1)
        {
            startskill = skill_t.values()[CM.getArgv(p+1).charAt(0)-'1'];
            autostart = true;
        }

        p = CM.CheckParm ("-episode");
        if (eval(p) && p < CM.getArgc()-1)
        {
            startepisode = CM.getArgv(p+1).charAt(0)-'0';
            startmap = 1;
            autostart = true;
        }

        p = CM.CheckParm ("-timer");
        if (eval(p) && p < CM.getArgc()-1 && deathmatch)
        {
            int     time;
            time = Integer.parseInt(CM.getArgv(p+1));
            System.out.print("Levels will end after "+time+" minute");
            if (time>1)
                System.out.print("s");
            System.out.print(".\n");
        }

        // OK, and exactly how is this enforced?
        p = CM.CheckParm ("-avg");
        if (eval(p) && p < CM.getArgc()-1 && deathmatch)
            System.out.print("Austin Virtual Gaming: Levels will end after 20 minutes\n");

        // MAES 31/5/2011: added support for +map variation.
        p = CM.CheckParm ("-warp");
        if (eval(p) && p < CM.getArgc()-1)
        {
            if (isCommercial())
                startmap = Integer.parseInt(CM.getArgv(p+1));
            else
            {
                int eval=11;
                try {
                    eval=Integer.parseInt(CM.getArgv(p+1));
                } catch (Exception e){
                    // swallow exception. No warp.
                }

                if (eval>99) eval%=100;

                if (eval<10) {
                    startepisode = 1;
                    startmap = 1;
                }
                else {
                    startepisode = eval/10;
                    startmap = eval%10;
                }
            }
            autostart = true;
        }

        // Maes: 1/6/2011 Added +map support
        p = CM.CheckParm ("+map");
        if (eval(p)) 
        {
            if (isCommercial()) {
                startmap = parseAsMapXX(CM.getArgv(p+1));
                if (startmap!=-1){
                	autostart = true;
            	}
            }
            else
            {
                int eval=parseAsExMx(CM.getArgv(p+1));
                if (eval!=-1){

                    startepisode = Math.max(1,eval/10);
                    startmap = Math.max(1,eval%10);
                    autostart = true;
                }
            }
            
        }
        
        // init subsystems
        System.out.print("V_Init: allocate screens.\n");
        V.Init ();
        

        System.out.print("Z_Init: Init zone memory allocation daemon. \n");
        // DUMMY: Z_Init ();

        System.out.print("W_Init: Init WADfiles.\n");
        try {
            W.InitMultipleFiles(wadfiles,true);
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        //
        System.out.print("VI_Init: set colormaps.\n");
        
        // MAES: FIX for incomplete palette lumps such as those in EGADOOM.
        // Generate the palette programmatically _anyway_
        byte[] pal=PaletteGenerator.generatePalette(PaletteGenerator.playpal,
        		256, ColorTint.tints);
        // Copy over the one you read from disk...
        int pallump=W.GetNumForName("PLAYPAL");
        byte[] tmppal=W.CacheLumpNumAsRawBytes(pallump, PU_STATIC);
        if (tmppal!=null)
        System.arraycopy(tmppal, 0, pal, 0, pal.length);
        
        V.createPalettes(pal, GammaTables.gammatables, 14, 256, 3, 5);
        
        W.InjectLumpNum(pallump,new DoomBuffer(ByteBuffer.wrap(pal)));
        // set it, create it, but don't make it visible yet.
        
        VI=selectVideoInterface();

        VI.InitGraphics();

        // MAES: Before we begin calling the various Init() stuff,
        // we need to make sure that objects that support the IVideoScaleAware
        // interface get set and initialized.

        initializeVideoScaleStuff();

        // MAES: The status bar needs this update because it can "force"
        // the video renderer to assign it a scratchpad screen (Screen 4).
        // Since we're at it, let's update everything, it's easy!
        
        this.updateStatusHolders(this);
        
        // Update variables and stuff NOW.
        this.update();

        // Check for -file in shareware
        CheckForPWADSInShareware();
        

        // Iff additonal PWAD files are used, printmodified banner
        
        if (modifiedgame)
        // Generate WAD loading alert. Abort upon denial.
        if (!I.GenerateAlert(Strings.MODIFIED_GAME_TITLE,Strings.MODIFIED_GAME_DIALOG)) {
        	  W.CloseAllHandles();
        	  System.exit(-2);
          }
        
        // Check and printwhich version is executed.
        switch ( getGameMode() )
        {
        case shareware:
        case indetermined:
            System.out.print("===========================================================================\n");
            System.out.print("                                Shareware!\n");
            System.out.print("===========================================================================\n");
            break;
        case registered:
        case retail:
        case commercial:
        case pack_tnt:
        case pack_plut:
        case pack_xbla:
            System.out.print("===========================================================================\n");
            System.out.print("                 Commercial product - do not distribute!\n");
            System.out.print("         Please report software piracy to the SPA: 1-800-388-PIR8\n");
            System.out.print("===========================================================================\n");
            break;

        default:
            // Ouch.
            break;
        }

        System.out.print("Tables.InitTables: Init trigonometric LUTs.\n");
        Tables.InitTables();

        System.out.print("M_Init: Init miscellaneous info.\n");
        M.Init ();

        System.out.print("R_Init: Init DOOM refresh daemon - ");
        R.Init ();
        
        System.out.print("AM_Init: Init Automap colors - ");
        AM.Init (); // Called here to set up configurable colors.

        System.out.print("\nP_Init: Init Playloop state.\n");
        P.Init ();

        System.out.print("I_Init: Setting up machine state.\n");
        I.Init ();

        System.out.print("D_CheckNetGame: Checking network game status.\n");
        CheckNetGame ();

        System.out.print("S_Init: Setting up sound.\n");
        
      // Sound "drivers" before the game sound controller.
        
        if (CM.CheckParmBool("-nomusic") || CM.CheckParmBool("-nosound"))
            this.IMUS=new DummyMusic();
        else
            this.IMUS=new DavidMusicModule();
        
        if (CM.CheckParmBool("-nosfx") ||  CM.CheckParmBool("-nosound"))
            this.ISND=new DummySFX();
        else {
            // Switch between possible sound drivers.
            // Crudish.
            if (CM.CheckParmBool("-audiolines"))
                this.ISND=	new DavidSFXModule(this,numChannels);
            else // PC Speaker emulation 
            if (CM.CheckParmBool("-speakersound"))
                this.ISND=  new SpeakerDoomSoundDriver(this,numChannels);
            else
            if (CM.CheckParmBool("-clipsound"))
                this.ISND=  new ClipSFXModule(this,numChannels);
            else  // This is the default
            if (CM.CheckParmBool("-classicsound"))
                this.ISND=  new ClassicDoomSoundDriver(this,numChannels);
            else  // This is the default
                this.ISND=  new SuperDoomSoundDriver(this,numChannels);

            }
        
        // Check for sound init failure and revert to dummy
        if (!ISND.InitSound()){
        	 System.err.println ("S_InitSound: failed. Reverting to dummy...\n");
        	this.ISND=new DummySFX();
        }
        
        if (!(CM.CheckParmBool("-nosound") || (ISND instanceof DummySFX)))// Obviously, nomusic && nosfx = nosound.
        	this.S=new AbstractDoomAudio(this,numChannels);
        else
        	// Saves a lot of distance calculations, 
        	// if we're not to output any sound at all.
            // TODO: create a Dummy that can handle music alone.
        	this.S=new DummySoundDriver();
        
        IMUS.InitMusic();
        S.Init (snd_SfxVolume *8, snd_MusicVolume *8 );

        // Hook audio to users.
        this.updateStatusHolders(this);
        
        System.out.print("HU_Init: Setting up heads up display.\n");
        HU.Init();

        System.out.print("ST_Init: Init status bar.\n");
        ST.Init ();

        // check for a driver that wants intermission stats
        p = CM.CheckParm ("-statcopy");
        if (eval(p) && p<CM.getArgc()-1)
        {
            // TODO: this should be chained to a logger
            //statcopy = CM.getArgv(p+1);
            System.out.print("External statistics registered.\n");
        }

        // start the apropriate game based on parms
        p = CM.CheckParm ("-record");

        if (eval(p) && p < CM.getArgc()-1)
        {
            RecordDemo (CM.getArgv(p+1));
            autostart = true;
        }
        
        // NOW it's safe to init the disk reader.
        DD.Init();

        // MAES: at this point everything should be set and initialized, so it's
        // time to make the players aware of the general status of Doom.
        //_D_ gonna try to initialize here, because it is needed to play a demo
        for (int i=0;i<MAXPLAYERS;i++){
            players[i].updateStatus(this);
        }

        //p = CM.CheckParm ("-timedemo");
        if (singletics)
        {
            TimeDemo (loaddemo);
            autostart = true;
            DoomLoop ();  // never returns
        }

        p = CM.CheckParm ("-loadgame");
        if (eval(p) && p < CM.getArgc()-1)
        {
            file.delete(0, file.length());
            if (eval(CM.CheckParm("-cdrom"))){
                file.append("c:\\doomdata\\");
                file.append(SAVEGAMENAME);
                file.append("%c.dsg");
                file.append(CM.getArgv(p+1).charAt(0));
            }
            else
            {
                file.append(String.format("%s%c.dsg",SAVEGAMENAME,
                    CM.getArgv(p+1).charAt(0)));

            }
            LoadGame(file.toString());
        }



        if ( gameaction != gameaction_t.ga_loadgame )
        {
            if (autostart || netgame)
                InitNew (startskill, startepisode, startmap);
            else
                StartTitle ();                // start up intro loop

        }


        if (fastdemo||normaldemo)
        {
            singledemo = true;              // quit after one demo
            if (fastdemo) timingdemo=true;
            InitNew (startskill, startepisode, startmap);
            gamestate=gamestate_t.GS_DEMOSCREEN;
            DeferedPlayDemo (loaddemo);
            DoomLoop ();  // never returns
        }

        
        
        DoomLoop ();  // never returns
    }


	protected abstract DoomVideoInterface<V> selectVideoInterface();


    protected int parseAsMapXX(String argv) {
    	
    	if (argv.length()!=5) return -1; // Nah.
    	if (argv.toLowerCase().lastIndexOf("map")!=0) return -1; // Meh.
    	int map;
    	try {
    		map=Integer.parseInt(argv.substring(3));
    	} catch (NumberFormatException e){
    		return -1; // eww
    	}
    	
		return map;
	}

    protected int parseAsExMx(String argv) {
    	
    	if (argv.length()!=4) return -1; // Nah.
    	if (argv.toLowerCase().lastIndexOf("e")!=0) return -1; // Meh.
    	if (argv.toLowerCase().lastIndexOf("m")!=2) return -1; // Meh.
    	int episode,mission;
    	try {
    		episode=Integer.parseInt(argv.substring(1,2));
    		mission=Integer.parseInt(argv.substring(3,4));
    	} catch (NumberFormatException e){
    		return -1; // eww
    	}
    	
		return episode*10+mission;
	}
    
	List<IVideoScaleAware> videoScaleChildren;

    public  void initializeVideoScaleStuff() {

        videoScaleChildren=new ArrayList<IVideoScaleAware>();

        // The automap...
        videoScaleChildren.add(this.AM);
        // The finale...
        videoScaleChildren.add(this.F);
        // The wiper...
        videoScaleChildren.add(this.WIPE);
        // The heads up...
        videoScaleChildren.add(this.HU);
        // The menu...
        videoScaleChildren.add(this.M);
        // The renderer (also has dependent children!)
        videoScaleChildren.add(this.R);
        // The Status Bar
        videoScaleChildren.add(this.ST);
        // Even the video renderer needs some initialization?
        videoScaleChildren.add(this.V);
        // wiper
        videoScaleChildren.add(this.WI);
        // disk drawer
        videoScaleChildren.add(this.DD);
        
        for(IVideoScaleAware i:videoScaleChildren){
            if (i!=null){
                i.setVideoScale(this.vs);
                i.initScaling();
            }
        }


    }


    /**
     * 
     */
    protected void CheckForPWADSInShareware() {
        if (modifiedgame)
        {
            // These are the lumps that will be checked in IWAD,
            // if any one is not present, execution will be aborted.
            String[] name=
            {
                    "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9",
                    "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9",
                    "dphoof","bfgga0","heada1","cybra1","spida1d1"
            };
            int i;

            // Oh yes I can.
            if ( isShareware())
                System.out.println("\nYou cannot -file with the shareware version. Register!");

            // Check for fake IWAD with right name,
            // but w/o all the lumps of the registered version. 
            if (isRegistered())
                for (i = 0;i < 23; i++)
                    if (W.CheckNumForName(name[i].toUpperCase())<0)
                        I.Error("\nThis is not the registered version: "+name[i]);
        }
    }

    /** Check whether the "doom.wad" we actually loaded
     *  is ultimate Doom's, by checking if it contains 
     *  e4m1 - e4m9.
     * 
     */
    protected void CheckForUltimateDoom(WadLoader W) {
        if (isRegistered())
        {
            // These are the lumps that will be checked in IWAD,
            // if any one is not present, execution will be aborted.
            String[] lumps=
            {
                    "e4m1","e4m2","e4m3","e4m4","e4m5","e4m6","e4m7","e4m8","e4m9"
            };

            // Check for fake IWAD with right name,
            // but w/o all the lumps of the registered version. 
            if (!CheckForLumps(lumps,W)) return;
            // Checks passed, so we can set the mode to Ultimate
            setGameMode(GameMode_t.retail);
        }

    }


    /** Check if ALL of the lumps exist.
     * 
     * @param name
     * @return
     */
    protected boolean CheckForLumps(String[] name, WadLoader W) {
        for (int i = 0;i < name.length; i++)
            if (W.CheckNumForName(name[i].toUpperCase())<0) {
                // Even one is missing? Not OK.
                return false; 
            }
        return true;
    }


    /**
     * 
     */
    protected void GenerateTitle() {
        switch ( getGameMode() )
        {
        case retail:
            title.append("                         ");
            title.append("The Ultimate DOOM Startup v");
            title.append(VERSION/100);
            title.append(".");
            title.append(VERSION%100);
            title.append("                           ");
            break;
        case shareware:
            title.append("                            ");
            title.append("DOOM Shareware Startup v");
            title.append(VERSION/100);
            title.append(".");
            title.append(VERSION%100);
            title.append("                           ");
            break;
        case registered:
            title.append("                            ");
            title.append("DOOM Registered Startup v");
            title.append(VERSION/100);
            title.append(".");
            title.append(VERSION%100);
            title.append("                           ");
            break;
        case commercial:
            title.append("                            ");
            title.append("DOOM 2: Hell on Earth v");
            title.append(VERSION/100);
            title.append(".");
            title.append(VERSION%100);
            title.append("                           ");

            break;
        case pack_plut:
            title.append("                            ");
            title.append("DOOM 2: Plutonia Experiment v");
            title.append(VERSION/100);
            title.append(".");
            title.append(VERSION%100);
            title.append("                           ");
            break;
        case pack_tnt:
            title.append("                            ");
            title.append("DOOM 2: TNT - Evilution v");
            title.append(VERSION/100);
            title.append(".");
            title.append(VERSION%100);
            title.append("                           ");
            break;
        case pack_xbla:
            title.append("                            ");
            title.append("DOOM 2: No Rest for the Living v");
            title.append(VERSION/100);
            title.append(".");
            title.append(VERSION%100);
            title.append("                           ");
            break;

        default:
            title.append("                            ");
            title.append("Public DOOM - v");
            title.append(VERSION/100);
            title.append(".");
            title.append(VERSION%100);
            title.append("                           ");
            break;
        }
    }

    // Used in BuildTiccmd.
    protected ticcmd_t   base=new ticcmd_t();

    /**
     * G_BuildTiccmd
     * Builds a ticcmd from all of the available inputs
     * or reads it from the demo buffer. 
     * If recording a demo, write it out .
     * 
     * The CURRENT event to process is written to the various 
     * gamekeydown etc. arrays by the Responder method.
     * So look there for any fuckups in constructing them.
     * 
     */ 

    private void BuildTiccmd (ticcmd_t cmd) 
    { 
        int     i; 
        boolean strafe;
        boolean bstrafe; 
        int     speed, tspeed,lspeed; 
        int     forward;
        int     side;
        int look;

        //base = I_BaseTiccmd ();     // empty, or external driver
        // memcpy (cmd,base,sizeof(*cmd));
        base.copyTo(cmd);

        cmd.consistancy =  consistancy[consoleplayer][maketic%BACKUPTICS]; 

        strafe = gamekeydown[key_strafe] || mousebuttons(mousebstrafe) 
        || joybuttons(joybstrafe); 
        speed = ((gamekeydown[key_speed]^alwaysrun) || joybuttons(joybspeed))?1:0;

        forward = side = look= 0;
        
        // use two stage accelerative turning
        // on the keyboard and joystick
        if (joyxmove < 0 || joyxmove > 0 ||
        	gamekeydown[key_right] || gamekeydown[key_left]) 
            turnheld += ticdup; 
        else 
            turnheld = 0; 

        if (turnheld < SLOWTURNTICS) 
            tspeed = 2;             // slow turn 
        else 
            tspeed = speed;

        if(gamekeydown[key_lookdown] || gamekeydown[key_lookup])
    	{
    		lookheld += ticdup;
    	}
    	else
    	{
    		lookheld = 0;
    	}
    	if(lookheld < SLOWTURNTICS)
    	{
    		lspeed = 1;
    	}
    	else
    	{
    		lspeed = 2;
    	}
        
        // let movement keys cancel each other out
        if (strafe) 
        { 
            if (gamekeydown[key_right]) 
            {
                // fprintf(stderr, "strafe right\n");
                side += sidemove[speed]; 
            }
            if (gamekeydown[key_left]) 
            {
                //  fprintf(stderr, "strafe left\n");
                side -= sidemove[speed]; 
            }
            if (joyxmove > 0) 
                side += sidemove[speed]; 
            if (joyxmove < 0) 
                side -= sidemove[speed]; 

        } 
        else 
        { 
            if (gamekeydown[key_right]) 
                cmd.angleturn -= angleturn[tspeed]; 
            if (gamekeydown[key_left]) 
                cmd.angleturn += angleturn[tspeed]; 
            if (joyxmove > 0) 
                cmd.angleturn -= angleturn[tspeed]; 
            if (joyxmove < 0) 
                cmd.angleturn += angleturn[tspeed]; 
        } 

        if (gamekeydown[key_up]) 
        {
            //System.err.print("up\n");
            forward += forwardmove[speed]; 
        }
        if (gamekeydown[key_down]) 
        {
            //System.err.print("down\n");
            forward -= forwardmove[speed]; 
        }        
        
        if (joyymove < 0) 
            forward += forwardmove[speed]; 
        if (joyymove > 0) 
            forward -= forwardmove[speed]; 
        if (gamekeydown[key_straferight]) 
            side += sidemove[speed]; 
        if (gamekeydown[key_strafeleft]) 
            side -= sidemove[speed];

    	// Look up/down/center keys
    	if(gamekeydown[key_lookup])
    	{
    		System.err.print("Look up\n");
    		look = lspeed;
    	}
    	
    	if(gamekeydown[key_lookdown])
    	{
    		System.err.print("Look down\n");
    		look = -lspeed;
    	}
    	
    	if(gamekeydown[key_lookcenter])
    	{
    		System.err.print("Center look\n");
    		look = TOCENTER;
    	}
    	
        // buttons
        cmd.chatchar = HU.dequeueChatChar(); 

        if (gamekeydown[key_fire] || mousebuttons(mousebfire) 
                || joybuttons(joybfire)) 
            cmd.buttons |= BT_ATTACK; 

        if (gamekeydown[key_use] || joybuttons(joybuse) ) 
        { 
            cmd.buttons |= BT_USE;
            // clear double clicks if hit use button 
            dclicks = 0;                   
        } 

        // chainsaw overrides 
        for (i=0 ; i<NUMWEAPONS-1 ; i++)        
            if (gamekeydown['1'+i]) 
            { 
                //System.out.println("Attempting weapon change (building ticcmd)");
                cmd.buttons |= BT_CHANGE; 
                cmd.buttons |= i<<BT_WEAPONSHIFT; 
                break; 
            }

        // mouse
        if (mousebuttons(mousebforward)) 
            forward += forwardmove[speed];

        // forward double click (operator precedence? && over >
        if (mousebuttons(mousebforward) != (dclickstate!=0) && (dclicktime > 1) ) 
        { 
            dclickstate = mousebuttons(mousebforward)?1:0; 
            if (dclickstate!=0) 
                dclicks++; 
            if (dclicks == 2) 
            { 
                cmd.buttons |= BT_USE; 
                dclicks = 0; 
            } 
            else 
                dclicktime = 0; 
        } 
        else 
        { 
            dclicktime += ticdup; 
            if (dclicktime > 20) 
            { 
                dclicks = 0; 
                dclickstate = 0; 
            } 
        }

        // strafe double click
        bstrafe = mousebuttons(mousebstrafe) || joybuttons(joybstrafe); 
        if ((bstrafe != (dclickstate2!=0)) && dclicktime2 > 1 ) 
        { 
            dclickstate2 = bstrafe?1:0; 
            if (dclickstate2!=0) 
                dclicks2++; 
            if (dclicks2 == 2) 
            { 
                cmd.buttons |= BT_USE; 
                dclicks2 = 0; 
            } 
            else 
                dclicktime2 = 0; 
        } 
        else 
        { 
            dclicktime2 += ticdup; 
            if (dclicktime2 > 20) 
            { 
                dclicks2 = 0; 
                dclickstate2 = 0; 
            } 
        } 

        // By default, no vertical mouse movement
        if (!novert) forward += mousey; 

        if (strafe) 
            side += mousex*2; 
        else 
            cmd.angleturn -= mousex*0x8; 

        mousex = mousey = 0; 

        if (forward > MAXPLMOVE()) 
            forward = MAXPLMOVE(); 
        else if (forward < -MAXPLMOVE()) 
            forward = -MAXPLMOVE(); 
        if (side > MAXPLMOVE()) 
            side = MAXPLMOVE(); 
        else if (side < -MAXPLMOVE()) 
            side = -MAXPLMOVE(); 

        cmd.forwardmove += forward; 
        cmd.sidemove += side;

    	if(players[consoleplayer].playerstate == PST_LIVE)
    	{
    		if(look < 0)
    		{
    			look += 16;
    		}
    		
    		cmd.lookfly = (char) look;
    	}
        
        // special buttons
        if (sendpause) 
        { 
            sendpause = false; 
            cmd.buttons = BT_SPECIAL | BTS_PAUSE; 
        } 

        if (sendsave) 
        { 
            sendsave = false; 
            cmd.buttons = (char) (BT_SPECIAL | BTS_SAVEGAME | (savegameslot<<BTS_SAVESHIFT)); 
        } 
    } 


    //
    // G_DoLoadLevel 
    //
    //extern  gamestate_t     wipegamestate; 

    public boolean DoLoadLevel () 
    { 
        int             i; 

        // Set the sky map.
        // First thing, we have a dummy sky texture name,
        //  a flat. The data is in the WAD only because
        //  we look for an actual index, instead of simply
        //  setting one.
        TM.setSkyFlatNum(TM.FlatNumForName ( SKYFLATNAME ));

        // DOOM determines the sky texture to be used
        // depending on the current episode, and the game version.
        if (isCommercial()
                || ( gamemission == GameMission_t.pack_tnt )
                || ( gamemission == GameMission_t.pack_plut ) )
        {
            TM.setSkyTexture(TM.TextureNumForName ("SKY3"));
            if (gamemap < 12)
                TM.setSkyTexture(TM.TextureNumForName ("SKY1"));
            else
                if (gamemap < 21)
                    TM.setSkyTexture(TM.TextureNumForName ("SKY2"));
        }

        levelstarttic = gametic;        // for time calculation

        if (wipegamestate == gamestate_t.GS_LEVEL) 
            wipegamestate = gamestate_t.GS_MINUS_ONE;             // force a wipe 

        gamestate = gamestate_t.GS_LEVEL; 

        for (i=0 ; i<MAXPLAYERS ; i++) 
        { 
            if (playeringame[i] && players[i].playerstate == PST_DEAD) 
                players[i].playerstate = PST_REBORN; 
            // I don't give a shit if it's not super-duper optimal. 
            Arrays.fill(players[i].frags, 0);

        } 

        try {
        LL.SetupLevel (gameepisode, gamemap, 0, gameskill);
        } catch (Exception e){
        	e.printStackTrace();
        	// Failure loading level.
        	return false;
        }
        
        displayplayer = consoleplayer;      // view the guy you are playing    
        gameaction = gameaction_t.ga_nothing; 
        //Z_CheckHeap ();

        // clear cmd building stuff
        Arrays.fill(gamekeydown, false);
        keysCleared = true;
        joyxmove = joyymove = 0; 
        mousex = mousey = 0; 
        sendpause = sendsave = paused = false; 
        Arrays.fill (mousearray, false);
        Arrays.fill(joyarray, false); 
        
        
        // killough 5/13/98: in case netdemo has consoleplayer other than green
        ST.Start();
        HU.Start();
        
        // killough: make -timedemo work on multilevel demos
        // Move to end of function to minimize noise -- killough 2/22/98:

        if (timingdemo)
          {
            if (first)
              {
                starttime = RealTime.GetTime();
                first=false;
              }
          }
        
        // Try reclaiming some memory from limit-expanded buffers.
        R.resetLimits();
        return true;
    } 
    
    protected boolean first=true;
    
    // Maes: needed because a caps lock down signal is issued
    // as soon as the app gains focus. This causes lock keys to respond.
    // With this hack, they are ignored (?) the first time this happens.
    public boolean justfocused=true;

    /**
     * G_Responder  
     * Get info needed to make ticcmd_ts for the players.
     */

    public boolean Responder (event_t ev) 
    { 
        // allow spy mode changes even during the demo
        if (gamestate == gamestate_t.GS_LEVEL && ev.type == evtype_t.ev_keydown 
                && ev.data1 == KEY_F12 && (singledemo || !deathmatch) )
        {
            // spy mode 
            do 
            { 
                displayplayer++; 
                if (displayplayer == MAXPLAYERS) 
                    displayplayer = 0; 
            } while (!playeringame[displayplayer] && displayplayer != consoleplayer); 
            return true; 
        }

        // any other key pops up menu if in demos
        if (gameaction == gameaction_t.ga_nothing && !singledemo && 
                (demoplayback || gamestate == gamestate_t.GS_DEMOSCREEN) 
        ) 
        { 
            if (ev.type == evtype_t.ev_keydown ||  
                    (ev.type == evtype_t.ev_mouse && ev.data1!=0) || 
                    (ev.type == evtype_t.ev_joystick && ev.data1!=0) ) 
            { 
                M.StartControlPanel (); 
                return true; 
            } 
            return false; 
        } 

        if (gamestate == gamestate_t.GS_LEVEL) 
        { 

            if (devparm && ev.type == evtype_t.ev_keydown && ev.data1 == ';') 
            { 
                DeathMatchSpawnPlayer (0); 
                return true; 
            } 

            //automapactive=true;

            if (HU.Responder (ev)) 
                return true;    // chat ate the event 
            if (ST.Responder (ev)) 
                return true;    // status window ate it
            if (AM.Responder (ev)) 
                return true;    // automap ate it 

        } 

        if (gamestate == gamestate_t.GS_FINALE) 
        { 
            if (F.Responder (ev)) 
                return true;    // finale ate the event 
        } 

        switch (ev.type) 
        {
        case ev_clear:
        	// PAINFULLY and FORCEFULLY clear the buttons.
            Arrays.fill(gamekeydown, false);
            keysCleared = true;
            return false; // Nothing more to do here. 
        case ev_keydown: 
            if (ev.data1 == KEY_PAUSE) 
            { 
                sendpause = true; 
                return true; 
            }
            
            /* CAPS lock will only go through as a keyup event
            if (ev.data1 == KEY_CAPSLOCK) 
            { 
                if (justfocused) justfocused=false;
                    else
                // If caps are turned on, turn autorun on anyway.
                if (!alwaysrun) {
                    alwaysrun=true;
                    players[consoleplayer].message=String.format("Always run: %s",alwaysrun);
                    }
                return true; 
            } */
            
            if (ev.data1 <NUMKEYS) 
                gamekeydown[ev.data1] = true;
            return true;    // eat key down events 

        case ev_keyup:
            if (ev.data1 == KEY_CAPSLOCK) 
            { 
                if (justfocused) justfocused=false;
                    else
                    {
                    // Just toggle it. It's too hard to read the state.
                    alwaysrun=!alwaysrun;
                    players[consoleplayer].message=String.format("Always run: %s",alwaysrun);
                    }
            }
            
            if (ev.data1 <NUMKEYS) 
                gamekeydown[ev.data1] = false; 
            return false;   // always let key up events filter down 

        case ev_mouse:
            // Ignore them at the responder level
            if (use_mouse){
            mousebuttons(0, ev.data1 & 1); 
            mousebuttons(1, ev.data1 & 2); 
            mousebuttons(2, ev.data1 & 4);
            mousex = ev.data2*(mouseSensitivity+5)/10; 
            mousey = ev.data3*(mouseSensitivity+5)/10;
            }
            return true;    // eat events 

        case ev_joystick:
            if (use_joystick){
            joybuttons(0, ev.data1 & 1); 
            joybuttons(1, ev.data1 & 2); 
            joybuttons(2,ev.data1 & 4); 
            joybuttons(3,ev.data1 & 8); 
            joyxmove = ev.data2; 
            joyymove = ev.data3; 
            }
            return true;    // eat events 

        default: 
            break; 
        } 

        return false; 
    } 


    private final String turbomessage="is turbo!"; 

    /**
     * G_Ticker
     * Make ticcmd_ts for the players.
     */

    public void Ticker () 
    { 
        int     i;
        int     buf; 
        ticcmd_t   cmd;

        // do player reborns if needed
        for (i=0 ; i<MAXPLAYERS ; i++) 
            if (playeringame[i] && players[i].playerstate == PST_REBORN) 
                DoReborn (i);

        // do things to change the game state
        while (gameaction != gameaction_t.ga_nothing) 
        { 
            switch (gameaction) 
            { 
            case ga_loadlevel: 
                DoLoadLevel ();
                break; 
            case ga_newgame: 
                DoNewGame (); 
                break; 
            case ga_loadgame:
                DoLoadGame (); 
                break; 
            case ga_savegame: 
                DoSaveGame (); 
                break; 
            case ga_playdemo: 
                DoPlayDemo (); 
                break; 
            case ga_completed: 
                DoCompleted (); 
                break; 
            case ga_victory: 
                F.StartFinale (); 
                break; 
            case ga_worlddone: 
                DoWorldDone (); 
                break; 
            case ga_screenshot: 
                ScreenShot (); 
                gameaction = gameaction_t.ga_nothing; 
                break; 
            case ga_nothing: 
                break; 
            } 
        }

        // get commands, check consistancy,
        // and build new consistancy check
        buf = (gametic/ticdup)%BACKUPTICS; 

        for (i=0 ; i<MAXPLAYERS ; i++)
        {
            if (playeringame[i]) 
            { 
                cmd = players[i].cmd; 
                //System.out.println("Current command:"+cmd);

                //memcpy (cmd, &netcmds[i][buf], sizeof(ticcmd_t));
                netcmds[i][buf].copyTo(cmd);

                // MAES: this is where actual demo commands are being issued or created!
                // Essentially, a demo is a sequence of stored ticcmd_t with a header.
                // Knowing that, it's possible to objectify it.
                if (demoplayback) 
                    ReadDemoTiccmd (cmd); 
                if (demorecording) 
                    WriteDemoTiccmd (cmd);

                // check for turbo cheats
                if (cmd.forwardmove > TURBOTHRESHOLD 
                        && ((gametic&31)==0) && ((gametic>>5)&3) == i )
                {

                    //extern char *player_names[4];
                    //sprintf (turbomessage, "%s is turbo!",player_names[i]);
                    players[consoleplayer].message = hu.HU.player_names[i]+turbomessage;
                }

                if (netgame && !netdemo && (gametic%ticdup)==0 ) 
                { 
                    if (gametic > BACKUPTICS 
                            && consistancy[i][buf] != cmd.consistancy) 
                    { 
                        I.Error ("consistency failure (%d should be %d)",
                            cmd.consistancy, consistancy[i][buf]); 
                    } 
                    if (players[i].mo!=null) 
                        consistancy[i][buf] = (short) players[i].mo.x; 
                    else 
                        consistancy[i][buf] = (short) RND.getIndex(); 
                } 
            }
        }

        // check for special buttons
        for (i=0 ; i<MAXPLAYERS ; i++)
        {
            if (playeringame[i]) 
            { 
                if ((players[i].cmd.buttons & BT_SPECIAL)!=0) 
                { 
                    switch (players[i].cmd.buttons & BT_SPECIALMASK) 
                    { 
                    case BTS_PAUSE:
                        // MAES: fixed stupid ^pause bug.
                        paused = !paused; 
                        if (paused)
                            S.PauseSound ();
                        else
                            S.ResumeSound (); 
                        break; 

                    case BTS_SAVEGAME: 
                        if (savedescription==null) 
                            savedescription=new String( "NET GAME"); 
                        savegameslot =  
                            (players[i].cmd.buttons & BTS_SAVEMASK)>>BTS_SAVESHIFT; 
        gameaction = gameaction_t.ga_savegame; 
        break; 
                    } 
                } 
            }
        }

        // do main actions
        switch (gamestate) 
        { 
        case GS_LEVEL: 
            P.Ticker (); 
            ST.Ticker (); 
            AM.Ticker (); 
            HU.Ticker ();            
            break; 

        case GS_INTERMISSION: 
            WI.Ticker (); 
            break; 

        case GS_FINALE: 
            F.Ticker (); 
            break; 

        case GS_DEMOSCREEN: 
            PageTicker (); 
            break; 
        }        
    } 


    //
    // PLAYER STRUCTURE FUNCTIONS
    // also see P_SpawnPlayer in P_Things
    //

    /**
     * G_InitPlayer
     * Called at the start.
     * Called by the game initialization functions.
     *
     * MAES: looks like dead code. It's never called.
     *
     */

    protected void InitPlayer (int player) 
    { 
        player_t   p; 

        // set up the saved info         
        p = players[player]; 

        // clear everything else to defaults 
        p.PlayerReborn (); 

    } 
    
    //
    // G_CheckSpot  
    // Returns false if the player cannot be respawned
    // at the given mapthing_t spot  
    // because something is occupying it 
    //
    //void P_SpawnPlayer (mapthing_t* mthing); 

    private boolean
    CheckSpot
    ( int       playernum,
            mapthing_t   mthing ) 
    { 
        int     x,y; // fixed_t 
        subsector_t    ss; 
        int        an; // angle 
        mobj_t     mo; 


        if (players[playernum].mo==null)
        {
            // first spawn of level, before corpses
            for (int i=0 ; i<playernum ; i++)
                if (players[i].mo.x == mthing.x << FRACBITS
                        && players[i].mo.y == mthing.y << FRACBITS)
                    return false;   
            return true;
        }

        x = mthing.x << FRACBITS; 
        y = mthing.y << FRACBITS; 

        if (!P.CheckPosition (players[playernum].mo, x, y) )
            return false;

        // flush an old corpse if needed 
        if (bodyqueslot >= BODYQUESIZE) 
            P.RemoveMobj (bodyque[bodyqueslot%BODYQUESIZE]); 
        bodyque[bodyqueslot%BODYQUESIZE] = players[playernum].mo; 
        bodyqueslot++; 

        // spawn a teleport fog 
        ss = LL.PointInSubsector (x,y); 
        // Angles stored in things are supposed to be "sanitized" against rollovers.
        an = (int) (( ANG45 * (mthing.angle/45) ) >>> ANGLETOFINESHIFT); 

        mo = P.SpawnMobj (x+20*finecosine[an], y+20*finesine[an] 
                                                             , ss.sector.floorheight 
                                                             , mobjtype_t.MT_TFOG); 

        if (players[consoleplayer].viewz != 1) ; 
        S.StartSound (mo, sfxenum_t.sfx_telept);  // don't start sound on first frame 

        return true; 
    } 


    //
    // G_DeathMatchSpawnPlayer 
    // Spawns a player at one of the random death match spots 
    // called at level load and each death 
    //
    @Override
    public void DeathMatchSpawnPlayer (int playernum) 
    { 
        int             i,j; 
        int             selections; 

        selections = deathmatch_p; 
        if (selections < 4) 
            I.Error ("Only %d deathmatch spots, 4 required", selections); 

        for (j=0 ; j<20 ; j++) 
        { 
            i = RND.P_Random() % selections; 
            if (CheckSpot (playernum, deathmatchstarts[i]) ) 
            { 
                deathmatchstarts[i].type = (short) (playernum+1); 
                P.SpawnPlayer (deathmatchstarts[i]); 
                return; 
            } 
        } 

        // no good spot, so the player will probably get stuck
        // MAES: seriously, fuck him.
        P.SpawnPlayer (playerstarts[playernum]); 
    } 

    //
    // G_DoReborn 
    // 

    public void DoReborn (int playernum) 
    { 
        int                             i; 

        if (!netgame)
        {
            // reload the level from scratch
            gameaction = gameaction_t.ga_loadlevel;  
        }
        else 
        {
            // respawn at the start

            // first dissasociate the corpse 
            players[playernum].mo.player = null;   

            // spawn at random spot if in death match 
            if (deathmatch) 
            { 
                DeathMatchSpawnPlayer (playernum); 
                return; 
            } 

            if (CheckSpot (playernum, playerstarts[playernum]) ) 
            { 
                P.SpawnPlayer (playerstarts[playernum]); 
                return; 
            }

            // try to spawn at one of the other players spots 
            for (i=0 ; i<MAXPLAYERS ; i++)
            {
                if (CheckSpot (playernum, playerstarts[i]) ) 
                { 
                    playerstarts[i].type = (short) (playernum+1); // fake as other player 
                    P.SpawnPlayer (playerstarts[i]); 
                    playerstarts[i].type = (short) (i+1);     // restore 
                    return; 
                }       
                // he's going to be inside something.  Too bad.
                // MAES: Yeah, they're like, fuck him.
            }
            P.SpawnPlayer (playerstarts[playernum]); 
        } 
    } 

    /** DOOM Par Times [4][10] */
    final int[][] pars = 
    { 
            {0}, 
            {0,30,75,120,90,165,180,180,30,165}, 
            {0,90,90,90,120,90,360,240,30,170}, 
            {0,90,45,90,150,90,90,165,30,135} 
    }; 

    /** DOOM II Par Times */
    final int[] cpars =
    {
            30,90,120,120,90,150,120,120,270,90,    //  1-10
            210,150,150,150,210,150,420,150,210,150,    // 11-20
            240,150,180,150,150,300,330,420,300,180,    // 21-30
            120,30                  // 31-32
    };


    //
    // G_DoCompleted 
    //
    boolean     secretexit; 

    public final void ExitLevel () 
    { 
        secretexit = false; 
        gameaction = gameaction_t.ga_completed; 
    } 

    // Here's for the german edition.
    public void SecretExitLevel () 
    { 
        // IF NO WOLF3D LEVELS, NO SECRET EXIT!
        if ( isCommercial()
                && (W.CheckNumForName("MAP31")<0))
            secretexit = false;
        else
            secretexit = true; 
        gameaction =  gameaction_t.ga_completed; 
    } 

    protected void DoCompleted () 
    { 
        int             i; 

        gameaction =  gameaction_t.ga_nothing; 

        for (i=0 ; i<MAXPLAYERS ; i++) 
            if (playeringame[i]) 
                players[i].PlayerFinishLevel ();        // take away cards and stuff 

        if (automapactive) 
            AM.Stop (); 

        if ( !isCommercial())
            switch(gamemap)
            {
            case 8:
                // MAES: end of episode
                gameaction =  gameaction_t.ga_victory;
                return;
            case 9:
                // MAES: end of secret level
                for (i=0 ; i<MAXPLAYERS ; i++) 
                    players[i].didsecret = true; 
                break;
            }

        /*  Hmmm - why? MAES: Clearly redundant.
        if ( (gamemap == 8)
                && (!isCommercial()) ) 
        {
            // victory 
            gameaction =  gameaction_t.ga_victory; 
            return; 
        } 

        if ( (gamemap == 9)
                && !isCommercial() ) 
        {
            // exit secret level 
            for (i=0 ; i<MAXPLAYERS ; i++) 
                players[i].didsecret = true; 
        } 
         */


        wminfo.didsecret = players[consoleplayer].didsecret; 
        wminfo.epsd = gameepisode -1; 
        wminfo.last = gamemap -1;

        // wminfo.next is 0 biased, unlike gamemap
        if ( isCommercial())
        {
            if (secretexit)
                switch(gamemap)
                {
                case 15: wminfo.next = 30; break;
                case 31: wminfo.next = 31; break;
                }
            else
                switch(gamemap)
                {
                case 31:
                case 32: wminfo.next = 15; break;
                default: wminfo.next = gamemap;
                }
        }
        else
        {
            if (secretexit) 
                wminfo.next = 8;    // go to secret level 
            else if (gamemap == 9) 
            {
                // returning from secret level 
                switch (gameepisode) 
                { 
                case 1: 
                    wminfo.next = 3; 
                    break; 
                case 2: 
                    wminfo.next = 5; 
                    break; 
                case 3: 
                    wminfo.next = 6; 
                    break; 
                case 4:
                    wminfo.next = 2;
                    break;
                }                
            } 
            else 
                wminfo.next = gamemap;          // go to next level 
        }

        wminfo.maxkills = totalkills; 
        wminfo.maxitems = totalitems; 
        wminfo.maxsecret = totalsecret; 
        wminfo.maxfrags = 0; 
        if ( isCommercial() )
            wminfo.partime = 35*cpars[gamemap-1]; 
        else if (gameepisode >= pars.length)
            wminfo.partime = 0;
        else
            wminfo.partime = 35*pars[gameepisode][gamemap]; 
        wminfo.pnum = consoleplayer; 

        for (i=0 ; i<MAXPLAYERS ; i++) 
        { 
            wminfo.plyr[i].in = playeringame[i]; 
            wminfo.plyr[i].skills = players[i].killcount; 
            wminfo.plyr[i].sitems = players[i].itemcount; 
            wminfo.plyr[i].ssecret = players[i].secretcount; 
            wminfo.plyr[i].stime = leveltime;
            C2JUtils.memcpy (wminfo.plyr[i].frags, players[i].frags 
                , wminfo.plyr[i].frags.length); 
        } 

        gamestate = gamestate_t.GS_INTERMISSION; 
        viewactive = false; 
        automapactive = false; 

        if (statcopy!=null)
            C2JUtils.memcpy (statcopy, wminfo,1);

        WI.Start (wminfo); 
    } 


    /**
     * G_WorldDone 
     */

    public void WorldDone () 
    { 
        gameaction = gameaction_t.ga_worlddone; 

        if (secretexit) 
            players[consoleplayer].didsecret = true; 

        if ( isCommercial() )
        {
            switch (gamemap)
            {
            case 15:
            case 31:
                if (!secretexit)
                    break;
            case 6:
            case 11:
            case 20:
            case 30:
                F.StartFinale ();
                break;
            }
        }
    } 

    public void DoWorldDone () 
    {        
        gamestate = gamestate_t.GS_LEVEL; 
        gamemap = wminfo.next+1; 
        DoLoadLevel (); 
        gameaction = gameaction_t.ga_nothing; 
        viewactive = true; 
    } 



    //
    // G_InitFromSavegame
    // Can be called by the startup code or the menu task. 
    //
    //extern boolean setsizeneeded;
    //void R_ExecuteSetViewSize (void);

    String    savename;

    public void LoadGame (String name) 
    { 
        savename=new String(name); 
        gameaction = gameaction_t.ga_loadgame; 
    } 



    /** This is fugly. Making a "savegame object" will make at least certain comparisons
     *  easier, and avoid writing code twice.
     */

    protected void DoLoadGame () 
    { 
        try{ 
            int     i;  
            StringBuffer vcheck=new StringBuffer();
            VanillaDSGHeader header=new VanillaDSGHeader();
            IDoomSaveGame dsg=new VanillaDSG();
            dsg.updateStatus(this.DM);
            
            gameaction = gameaction_t.ga_nothing; 

            DataInputStream f=new DataInputStream(new BufferedInputStream(new FileInputStream(savename))); 

            header.read(f);
            f.close();
    
            // skip the description field 
            vcheck.append("version ");
            vcheck.append(VERSION);

            if (vcheck.toString().compareTo(header.getVersion())!=0) {
            	f.close();
            	return; // bad version
            }

            // Ok so far, reopen stream.
            f=new DataInputStream(new BufferedInputStream(new FileInputStream(savename)));        
            gameskill = header.getGameskill(); 
            gameepisode = header.getGameepisode(); 
            gamemap = header.getGamemap(); 
            for (i=0 ; i<MAXPLAYERS ; i++) 
                playeringame[i] = header.getPlayeringame()[i]; 

            // load a base level 
            InitNew (gameskill, gameepisode, gamemap); 
            
            if (gameaction == gameaction_t.ga_failure) {
            	// failure to load. Abort.
            	f.close();
            	return;
            }

            gameaction = gameaction_t.ga_nothing;
            
            // get the times 
            leveltime = header.getLeveltime(); 

            // dearchive all the modifications
            boolean ok=dsg.doLoad(f);
            f.close();

            // MAES: this will cause a forced exit.
            // The problem is that the status will have already been altered 
            // (perhaps VERY badly) so it makes no sense to progress.
            // If you want it bullet-proof, you could implement
            // a "tentative loading" subsystem, which will only alter the game
            // if everything works out without errors. But who cares :-p
            if (!ok) 
                I.Error("Bad savegame");

            // done 
            //Z_Free (savebuffer); 

            if (R.getSetSizeNeeded())
                R.ExecuteSetViewSize ();

            // draw the pattern into the back screen
            R.FillBackScreen ();   
        } catch (Exception e){
            e.printStackTrace();
        }
    } 


    //
    // G_SaveGame
    // Called by the menu task.
    // Description is a 24 byte text string 
    //
    public void
    SaveGame
    ( int   slot,
            String description ) 
    { 
        savegameslot = slot; 
        savedescription=new String(description); 
        sendsave = true; 
    } 

    protected void DoSaveGame () 
    { 
     
        try{
     String    name; 
     //char[]    name2=new char[VERSIONSIZE]; 
     String   description;
     StringBuffer build=new StringBuffer();
     IDoomSaveGameHeader header=new VanillaDSGHeader();
     IDoomSaveGame dsg=new VanillaDSG();
     dsg.updateStatus(this.DM);
     
     if (eval(CM.CheckParm("-cdrom"))) {
         build.append("c:\\doomdata\\");
         build.append(SAVEGAMENAME);
         build.append("%d.dsg");
     } else {         
      build.append(SAVEGAMENAME);
      build.append("%d.dsg"); 
     }
     
     name=String.format(build.toString(), savegameslot);
     
     description = savedescription; 

     header.setName(description);
     header.setVersion(String.format("version %d",VERSION));
     header.setGameskill(gameskill);
     header.setGameepisode(gameepisode);
     header.setGamemap(gamemap);
     header.setPlayeringame(playeringame);
     header.setLeveltime(leveltime);
     dsg.setHeader(header);
     
     // Try opening a save file. No intermediate buffer (performance?)
     DataOutputStream f=new DataOutputStream(new FileOutputStream(name));
     boolean ok=dsg.doSave(f);
     f.close();
        } catch (Exception e){
            e.printStackTrace();
        }
     // Saving is not as destructive as loading.
     
     gameaction = gameaction_t.ga_nothing; 
        savedescription = "";      

        players[consoleplayer].message = GGSAVED; 

        // draw the pattern into the back screen
        R.FillBackScreen ();
     

    } 



    skill_t d_skill; 
    int     d_episode; 
    int     d_map; 

    public void
    DeferedInitNew
    ( skill_t   skill,
            int       episode,
            int       map) 
    { 
        d_skill = skill; 
        d_episode = episode; 
        d_map = map; 
        gameaction = gameaction_t.ga_newgame; 
    } 


    public void DoNewGame () 
    {
        demoplayback = false; 
        netdemo = false;
        netgame = false;
        deathmatch = false;
        playeringame[1] = playeringame[2] = playeringame[3] = false;
        respawnparm = false;
        fastparm = false;
        nomonsters = false;
        consoleplayer = 0;
        InitNew (d_skill, d_episode, d_map); 
        gameaction = gameaction_t.ga_nothing; 
    } 


    /**
     * G_InitNew
     * Can be called by the startup code or the menu task,
     * consoleplayer, displayplayer, playeringame[] should be set. 
     */

    public void InitNew
    ( skill_t   skill,
            int       episode,
            int       map ) 
    { 
        int             i; 

        if (paused) 
        { 
            paused = false; 
            S.ResumeSound (); 
        } 


        if (skill.ordinal() > skill_t.sk_nightmare.ordinal()) 
            skill = skill_t.sk_nightmare;


        // This was quite messy with SPECIAL and commented parts.
        // Supposedly hacks to make the latest edition work.
        // It might not work properly.
        if (episode < 1)
            episode = 1; 

        if ( isRetail() )
        {
            if (episode > 4)
                episode = 4;
        }
        else if ( isShareware() )
        {
            if (episode > 1) 
                episode = 1; // only start episode 1 on shareware
        }  
        else
        {
            if (episode > 3)
                episode = 3;
        }



        if (map < 1) 
            map = 1;

        if ( (map > 9)
                && ( !isCommercial()))
            map = 9; 

        RND.ClearRandom (); 

        if (skill == skill_t.sk_nightmare || respawnparm )
            respawnmonsters = true;
        else
            respawnmonsters = false;

        // If on nightmare/fast monsters make everything MOAR pimp.

        if (fastparm || (skill == skill_t.sk_nightmare && gameskill != skill_t.sk_nightmare) )
        { 
            for (i=statenum_t.S_SARG_RUN1.ordinal() ; i<=statenum_t.S_SARG_PAIN2.ordinal() ; i++) 
                states[i].tics >>= 1; 
            mobjinfo[mobjtype_t.MT_BRUISERSHOT.ordinal()].speed = 20*MAPFRACUNIT; 
            mobjinfo[mobjtype_t.MT_HEADSHOT.ordinal()].speed = 20*MAPFRACUNIT; 
            mobjinfo[mobjtype_t.MT_TROOPSHOT.ordinal()].speed = 20*MAPFRACUNIT; 
        } 
        else if (skill != skill_t.sk_nightmare && gameskill == skill_t.sk_nightmare) 
        { 
            for (i=statenum_t.S_SARG_RUN1.ordinal() ; i<=statenum_t.S_SARG_PAIN2.ordinal() ; i++) 
                states[i].tics <<= 1; 
            mobjinfo[mobjtype_t.MT_BRUISERSHOT.ordinal()].speed = 15*MAPFRACUNIT; 
            mobjinfo[mobjtype_t.MT_HEADSHOT.ordinal()].speed = 10*MAPFRACUNIT; 
            mobjinfo[mobjtype_t.MT_TROOPSHOT.ordinal()].speed = 10*MAPFRACUNIT; 
        } 


        // force players to be initialized upon first level load         
        for (i=0 ; i<MAXPLAYERS ; i++) 
            players[i].playerstate = PST_REBORN; 

        usergame = true;                // will be set false if a demo 
        paused = false; 
        demoplayback = false; 
        automapactive = false; 
        viewactive = true; 
        gameepisode = episode; 
        gamemap = map; 
        gameskill = skill; 

        viewactive = true;

        // set the sky map for the episode
        if ( isCommercial())
        {
            TM.setSkyTexture(TM.TextureNumForName ("SKY3"));
            if (gamemap < 12)
                TM.setSkyTexture(TM.TextureNumForName ("SKY1"));
            else
                if (gamemap < 21)
                    TM.setSkyTexture(TM.TextureNumForName ("SKY2"));
        }
        else
            switch (episode) 
            { 
            case 1: 
                TM.setSkyTexture(TM.TextureNumForName ("SKY1")); 
                break; 
            case 2: 
                TM.setSkyTexture(TM.TextureNumForName ("SKY2"));
                break; 
            case 3: 
                TM.setSkyTexture(TM.TextureNumForName ("SKY3")); 
                break; 
            case 4:   // Special Edition sky
                TM.setSkyTexture(TM.TextureNumForName ("SKY4"));
                break;
            } 

        if (!DoLoadLevel ()) levelLoadFailure();
    } 

    protected void levelLoadFailure(){
    	boolean endgame=I.GenerateAlert(Strings.LEVEL_FAILURE_TITLE, Strings.LEVEL_FAILURE_CAUSE);
    	
    	if (endgame){         	// Initiate endgame
    	gameaction=gameaction_t.ga_failure;
    	gamestate = gamestate_t.GS_DEMOSCREEN; 
    	M.ClearMenus();
    	StartTitle();
    	} else {
    	// Shutdown immediately.
    	I.Quit();	
    	}
    }

    //
    // DEMO RECORDING 
    // 
    public  void ReadDemoTiccmd (ticcmd_t cmd) 
    { 
        IDemoTicCmd democmd=demobuffer.getNextTic();
        if (democmd == null) 
        {
            // end of demo data stream 
            CheckDemoStatus ();

            // Force status resetting
            this.demobuffer.resetDemo();
            return; 
        }

        democmd.decode(cmd); 
    } 

    public void WriteDemoTiccmd (ticcmd_t cmd) 
    { 
        if (gamekeydown['q'])           // press q to end demo recording 
            CheckDemoStatus ();
        IDemoTicCmd reccmd=new VanillaTiccmd();
        reccmd.encode(cmd);     
        demobuffer.putTic(reccmd);

        // MAES: Useless, we can't run out of space anymore (at least not in theory).

        /*   demobuffer[demo_p++] = cmd.forwardmove; 
     demobuffer[demo_p++] = cmd.sidemove; 
     demobuffer[demo_p++] = (byte) ((cmd.angleturn+128)>>8); 
     demobuffer[demo_p++] = (byte) cmd.buttons; 
     demo_p -= 4; 
     if (demo_p > demoend - 16)
     {
     // no more space 
     CheckDemoStatus (); 
     return; 
     } */ 

        //ReadDemoTiccmd (cmd);         // make SURE it is exactly the same
        // MAES: this is NOT the way to do in Mocha, because we are not manipulating
        // the demo index directly anymore. Instead, decode what we have just saved.     
        reccmd.decode(cmd);

    } 



    /**
     * G_RecordDemo 
     */ 
    public void RecordDemo (String name) 
    { 

        StringBuffer buf=new StringBuffer();
        usergame = false; 
        buf.append(name); 
        buf.append(".lmp");
        demoname=buf.toString();
        demobuffer = new VanillaDoomDemo(); 
        demorecording = true; 
    } 


    public void BeginRecording () 
    {         
        demobuffer.setVersion(VERSION);
        demobuffer.setSkill(gameskill); 
        demobuffer.setEpisode(gameepisode);
        demobuffer.setMap(gamemap);
        demobuffer.setDeathmatch(deathmatch);
        demobuffer.setRespawnparm(respawnparm);
        demobuffer.setFastparm(fastparm);
        demobuffer.setNomonsters(nomonsters);
        demobuffer.setConsoleplayer(consoleplayer);
        demobuffer.setPlayeringame(playeringame);
    }
    
    String   defdemoname;
    
    /**
     * G_PlayDemo 
     */

    public void DeferedPlayDemo (String name) 
    { 
        defdemoname = name; 
        gameaction = gameaction_t.ga_playdemo; 
    } 

    public void DoPlayDemo () 
    { 

        skill_t skill;
        boolean fail=false;
        int             i, episode, map; 

        gameaction = gameaction_t.ga_nothing;
        // MAES: Yeah, it's OO all the way now, baby ;-)
        try {
        demobuffer = (IDoomDemo) W.CacheLumpName(defdemoname.toUpperCase(), PU_STATIC,VanillaDoomDemo.class);
        } catch (Exception e){
            fail=true;
        }
        
        fail=(demobuffer.getSkill()==null);

        if (fail || demobuffer.getVersion()!= VERSION)
        {
            System.err.println("Demo is from a different game version!\n");
            System.err.println("Version code read: "+demobuffer.getVersion());
            gameaction = gameaction_t.ga_nothing;
            return;
        }

        skill = demobuffer.getSkill(); 
        episode = demobuffer.getEpisode(); 
        map = demobuffer.getMap(); 
        deathmatch = demobuffer.isDeathmatch();
        respawnparm = demobuffer.isRespawnparm();
        fastparm = demobuffer.isFastparm();
        nomonsters = demobuffer.isNomonsters();
        consoleplayer = demobuffer.getConsoleplayer();
        // Do this, otherwise previously loaded demos will be stuck at their end.
        demobuffer.resetDemo();
        
        boolean[] pigs=demobuffer.getPlayeringame();
        for (i=0 ; i<MAXPLAYERS ; i++) 
            playeringame[i] = pigs[i]; 
        if (playeringame[1]) 
        {
            netgame = true; 
            netdemo = true; 
        }

        // don't spend a lot of time in loadlevel 
        precache = false;
        InitNew (skill, episode, map); 
        precache = true;

        usergame = false; 
        demoplayback = true; 

    }

    //
    // G_TimeDemo 
    //
    public void TimeDemo (String name) 
    {    
        nodrawers = CM.CheckParm ("-nodraw")!=0; 
        noblit = CM.CheckParm ("-noblit")!=0; 
        timingdemo = true; 
        singletics = true;
        defdemoname = name;
        gameaction = gameaction_t.ga_playdemo; 
    } 

    
    /** G_CheckDemoStatus
     * 
     * Called after a death or level completion to allow demos to be cleaned up
     * Returns true if a new demo loop action will take place
     *  
     */ 

    public boolean CheckDemoStatus () 
    { 
        int endtime; 
        
        if (timingdemo) 
        {
            endtime = RealTime.GetTime ();
            // killough -- added fps information and made it work for longer demos:
            long realtics=endtime-starttime;    
            
            this.commit();
            VM.SaveDefaults(VM.getDefaultFile());
            I.Error ("timed %d gametics in %d realtics = %f frames per second",gametic 
                , realtics, gametic*(double)(TICRATE)/realtics); 
        }

        if (demoplayback) 
        {
            if (singledemo) 
                I.Quit ();

            // Z_ChangeTag (demobuffer, PU_CACHE); 
            demoplayback = false; 
            netdemo = false;
            netgame = false;
            deathmatch = false;
            playeringame[1] = playeringame[2] = playeringame[3] = false;
            respawnparm = false;
            fastparm = false;
            nomonsters = false;
            consoleplayer = 0;
            AdvanceDemo (); 
            return true; 
        } 

        if (demorecording) 
        { 
            //demobuffer[demo_p++] = (byte) DEMOMARKER; 

            MenuMisc.WriteFile(demoname, demobuffer); 
            //Z_Free (demobuffer); 
            demorecording = false; 
            I.Error ("Demo %s recorded",demoname); 
        } 

        return false; 
    } 

    /** This should always be available for real timing */
    protected ITicker RealTime;
    
    public DoomMain(){
        // Init game status...
        super();
        C2JUtils.initArrayOfObjects(events,event_t.class);
        this.I=new DoomSystem();
        gamestate=gamestate_t.GS_DEMOSCREEN;        
        
        this.RealTime=new MilliTicker();
    }

   
    
    protected void updateStatusHolders(DoomStatus<T,V> DS){
        for (DoomStatusAware dsa : status_holders){
            dsa.updateStatus(DS);
        }
    }

    /** A list with objects that do hold status and need to be aware of 
     *  it.
     */
    protected List<DoomStatusAware> status_holders;

 


    /* Since it's so intimately tied, it's less troublesome to merge the "main" and "network"
     *  code. 
     * 
     */


    /** To be initialized by the DoomNetworkingInterface via a setter */
    //private  doomcom_t   doomcom;   
    //private  doomdata_t  netbuffer;      // points inside doomcom
    protected StringBuilder sb=new StringBuilder();


    //
    // NETWORKING
    //
    // gametic is the tic about to (or currently being) run
    // maketic is the tick that hasn't had control made for it yet
    // nettics[] has the maketics for all players 
    //
    // a gametic cannot be run until nettics[] > gametic for all players
    //

    //ticcmd_t[]  localcmds= new ticcmd_t[BACKUPTICS];

    //ticcmd_t [][]       netcmds=new ticcmd_t [MAXPLAYERS][BACKUPTICS];
    int[]           nettics=new int[MAXNETNODES];
    boolean[]       nodeingame=new boolean[MAXNETNODES];        // set false as nodes leave game
    boolean[]       remoteresend=new boolean[MAXNETNODES];      // set when local needs tics
    int[]       resendto=new int[MAXNETNODES];          // set when remote needs tics
    int[]       resendcount=new int[MAXNETNODES];

    int[]       nodeforplayer=new int[MAXPLAYERS];

    int             maketic;
    int     lastnettic;
    int     skiptics;
    protected int     ticdup;


    public int getTicdup() {
        return ticdup;
    }


    public void setTicdup(int ticdup) {
        this.ticdup = ticdup;
    }






    int     maxsend; // BACKUPTICS/(2*ticdup)-1;


    //void D_ProcessEvents (void); 
    //void G_BuildTiccmd (ticcmd_t *cmd); 
    //void D_DoAdvanceDemo (void);

    // _D_
    boolean     reboundpacket = false;
    doomdata_t  reboundstore = new doomdata_t();


    // 
    //
    //123

    /** MAES: interesting. After testing it was found to return the following size:
     *  (8*(netbuffer.numtics+1));
     */

    int NetbufferSize ()
    {
        //    return (int)(((doomdata_t)0).cmds[netbuffer.numtics]);
        return (8*(netbuffer.numtics+1));
    }


    protected long NetbufferChecksum ()
    {
        long        c;
        int     i,l;

        c = 0x1234567L;

        // FIXME -endianess?
        if (NORMALUNIX)
            return 0;           // byte order problems


        /* Here it was trying to get the length of a doomdata_t struct up to retransmit from.
         * l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
         * (int)&(((doomdata_t *)0)->retransmitfrom) evaluates to "4"
         * Therefore, l= (netbuffersize - 4)/4
         * 
         */
        l = (NetbufferSize () - 4)/4;
        for (i=0 ; i<l ; i++)
            // TODO: checksum would be better computer in the netbuffer itself.
            // The C code actually takes all fields into account.
            c += 0;// TODO: (netbuffer->retransmitfrom)[i] * (i+1);

        return c & NCMD_CHECKSUM;
    }
    //
    //
    //
    protected int ExpandTics (int low)
    {
        int delta;

        delta = low - (maketic&0xff);

        if (delta >= -64 && delta <= 64)
            return (maketic&~0xff) + low;
        if (delta > 64)
            return (maketic&~0xff) - 256 + low;
        if (delta < -64)
            return (maketic&~0xff) + 256 + low;

        I.Error ("ExpandTics: strange value %d at maketic %d",low,maketic);
        return 0;
    }



    /**
     * HSendPacket
     *
     * Will send out a packet to all involved parties. A special
     * case is the rebound storage, which acts as a local "echo"
     * which is then picked up by the host itself. This is
     * necessary to simulate a 1-node network.
     * @throws IOException 
     *
     */
    void
    HSendPacket
    (int   node,
            int   flags )
    {
        netbuffer.checksum = (int) (NetbufferChecksum () | flags);

        // Local node's comms are sent to rebound packet, which is 
        // then picked up again. THIS IS VITAL FOR SINGLE-PLAYER
        // SPEED THROTTLING TOO, AS IT RELIES ON NETWORK ACKS/BUSY
        // WAITING.
        if (node==0)
        {
            // _D_
            reboundstore.copyFrom(netbuffer);
            reboundpacket = true;
            return;
        }

        if (DM.demoplayback)
            return;

        if (!DM.netgame)
            I.Error ("Tried to transmit to another node");

        doomcom.command = CMD_SEND;
        doomcom.remotenode = (short) node;
        doomcom.datalength = (short) NetbufferSize ();

        if (DM.debugfile!=null)
        {
            int     i;
            int     realretrans;
            if (flags(netbuffer.checksum , NCMD_RETRANSMIT))
                realretrans = ExpandTics (netbuffer.retransmitfrom);
            else
                realretrans = -1;

            logger(debugfile,"send ("+ExpandTics(netbuffer.starttic)+", "+netbuffer.numtics + ", R "+
                realretrans+ "["+ doomcom.datalength+"]");

            for (i=0 ; i<doomcom.datalength ; i++)

                // TODO: get a serialized string representation.
            	logger(debugfile,netbuffer.toString()+"\n");
        }

        // This should execute a "send" command for the current stuff in doomcom.
        DNI.NetCmd ();
    }

    //
    // HGetPacket
    // Returns false if no packet is waiting
    //
    private boolean HGetPacket () 
    {   
        // Fugly way of "clearing" the buffer.
        sb.setLength(0);
        if (reboundpacket)
        {
            // FIXME: MAES: this looks like a struct copy 
            netbuffer.copyFrom(reboundstore);
            doomcom.remotenode = 0;
            reboundpacket = false;
            return true;
        }

        // If not actually a netgame (e.g. single player, demo) return.
        if (!DM.netgame)
            return false;

        if (DM.demoplayback)
            return false;

        doomcom.command = CMD_GET;
        DNI.NetCmd ();

        // Invalid node?
        if (doomcom.remotenode == -1)
            return false;

        if (doomcom.datalength != NetbufferSize ())
        {
            if (eval(debugfile))
            	logger(debugfile,"bad packet length "+doomcom.datalength+"\n");
            return false;
        }

        if (NetbufferChecksum () != (netbuffer.checksum&NCMD_CHECKSUM) )
        {
            if (eval(debugfile))
            	logger(debugfile,"bad packet checksum\n");
            return false;
        }

        if (eval(debugfile))
        {
            int     realretrans;
            int i;

            if (flags(netbuffer.checksum , NCMD_SETUP))
            	logger(debugfile,"setup packet\n");
            else
            {
                if (flags(netbuffer.checksum , NCMD_RETRANSMIT))
                    realretrans = ExpandTics (netbuffer.retransmitfrom);
                else
                    realretrans = -1;

                sb.append("get ");
                sb.append(doomcom.remotenode);
                sb.append(" = (");
                sb.append(ExpandTics(netbuffer.starttic));
                sb.append(" + ");
                sb.append(netbuffer.numtics);
                sb.append(", R ");
                sb.append(realretrans);
                sb.append(")[");
                sb.append(doomcom.datalength);
                sb.append("]");

                logger(debugfile,sb.toString());

                // Trick: force update of internal buffer.
                netbuffer.pack();

                /* TODO: Could it be actually writing stuff beyond the boundaries of a single doomdata object?
                 * A doomcom object has a lot of header info, and a single "raw" data placeholder, which by now
                 * should be inside netbuffer....right?
                 * 
                 * 
                 */

                try{
                    for (i=0 ; i<doomcom.datalength ; i++) {
                    	debugfile.write(Integer.toHexString(netbuffer.cached()[i]));
                    	debugfile.write('\n');
                    }
                }
                catch( IOException e){
                    // "Drown" IOExceptions here.
                }
            }
        }
        return true;    
    }


    ////    GetPackets

    StringBuilder exitmsg=new StringBuilder(80);

    public void GetPackets () 
    {
        int     netconsole;
        int     netnode;
        ticcmd_t    src, dest;
        int     realend;
        int     realstart;

        while ( HGetPacket() )
        {
            if (flags(netbuffer.checksum , NCMD_SETUP))
                continue;       // extra setup packet

            netconsole = netbuffer.player & ~PL_DRONE;
            netnode = doomcom.remotenode;

            // to save bytes, only the low byte of tic numbers are sent
            // Figure out what the rest of the bytes are
            realstart = ExpandTics (netbuffer.starttic);        
            realend = (realstart+netbuffer.numtics);

            // check for exiting the game
            if (flags(netbuffer.checksum , NCMD_EXIT))
            {
                if (!nodeingame[netnode])
                    continue;
                nodeingame[netnode] = false;
                playeringame[netconsole] = false;
                exitmsg.insert(0, "Player 1 left the game");
                exitmsg.setCharAt(7,(char) (exitmsg.charAt(7)+netconsole));
                players[consoleplayer].message = exitmsg.toString();
                if (demorecording)
                    DM.CheckDemoStatus ();
                continue;
            }

            // check for a remote game kill
            if (flags(netbuffer.checksum , NCMD_KILL))
                I.Error ("Killed by network driver");

            nodeforplayer[netconsole] = netnode;

            // check for retransmit request
            if ( resendcount[netnode] <= 0 
                    && flags(netbuffer.checksum , NCMD_RETRANSMIT) )
            {
                resendto[netnode] = ExpandTics(netbuffer.retransmitfrom);
                if (eval(debugfile)){
                    sb.setLength(0);
                    sb.append("retransmit from ");
                    sb.append(resendto[netnode]);
                    sb.append('\n');
                    logger(debugfile,sb.toString());
                    resendcount[netnode] = RESENDCOUNT;
                }
            }
            else
                resendcount[netnode]--;

            // check for out of order / duplicated packet       
            if (realend == nettics[netnode])
                continue;

            if (realend < nettics[netnode])
            {
                if (eval(debugfile)){
                    sb.setLength(0);
                    sb.append("out of order packet (");
                    sb.append(realstart);
                    sb.append(" + ");
                    sb.append(netbuffer.numtics);
                    sb.append(")\n");
                    logger(debugfile,sb.toString());
                }
                continue;
            }

            // check for a missed packet
            if (realstart > nettics[netnode])
            {
                // stop processing until the other system resends the missed tics
                if (eval(debugfile)) {
                    sb.setLength(0);
                    sb.append("missed tics from ");
                    sb.append(netnode);
                    sb.append(" (");
                    sb.append(realstart);
                    sb.append(" - ");
                    sb.append(nettics[netnode]);
                    sb.append(")\n");
                    logger(debugfile,sb.toString());
                }
                remoteresend[netnode] = true;
                continue;
            }

            // update command store from the packet
            {
                int     start;

                remoteresend[netnode] = false;

                start = nettics[netnode] - realstart;       
                src = netbuffer.cmds[start];

                while (nettics[netnode] < realend)
                {
                    dest = netcmds[netconsole][nettics[netnode]%BACKUPTICS];
                    nettics[netnode]++;
                    // MAES: this is a struct copy.
                    src.copyTo(dest);
                    // Advance src
                    start++;

                    //_D_: had to add this (see linuxdoom source). That fixed that damn consistency failure!!!
                    if (start < netbuffer.cmds.length)
                        src = netbuffer.cmds[start];

                }
            }
        }
    }

    protected void logger(OutputStreamWriter debugfile, String string) {
    		try {
				debugfile.write(string);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
	}

	int      gametime;

    @Override
    public void NetUpdate ()
    {
        int             nowtime;
        int             newtics;
        int             i,j;
        int             realstart;
        int             gameticdiv;

        // check time
        nowtime = TICK.GetTime ()/ticdup;
        newtics = nowtime - gametime;
        gametime = nowtime;

        if (newtics <= 0)   // nothing new to update
        {
            // listen for other packets
            GetPackets ();
            return;
        } else {


            if (skiptics <= newtics)
            {
                newtics -= skiptics;
                skiptics = 0;
            }
            else
            {
                skiptics -= newtics;
                newtics = 0;
            }

            netbuffer.player = (byte) consoleplayer;

            // build new ticcmds for console player
            gameticdiv = gametic/ticdup;
            for (i=0 ; i<newtics ; i++)
            {
                VI.StartTic ();
                ProcessEvents ();
                if (maketic - gameticdiv >= BACKUPTICS/2-1)
                    break;          // can't hold any more

                //System.out.printf ("mk:%d ",maketic);
                BuildTiccmd (localcmds[maketic%BACKUPTICS]);
                maketic++;
            }


            if (singletics)
                return;         // singletic update is syncronous

            // send the packet to the other nodes
            for (i=0 ; i<doomcom.numnodes ; i++)
                if (nodeingame[i])
                {
                    netbuffer.starttic = (byte) (realstart = resendto[i]);
                    netbuffer.numtics = (byte) (maketic - realstart);
                    if (netbuffer.numtics > BACKUPTICS)
                        I.Error ("NetUpdate: netbuffer.numtics > BACKUPTICS");

                    resendto[i] = maketic - doomcom.extratics;

                    for (j=0 ; j< netbuffer.numtics ; j++)
                        localcmds[(realstart+j)%BACKUPTICS].copyTo(netbuffer.cmds[j]);
                    // MAES: one of _D_ fixes.
                    //netbuffer.cmds[j] = localcmds[(realstart+j)%BACKUPTICS];

                    if (remoteresend[i])
                    {
                        netbuffer.retransmitfrom = (byte) nettics[i];
                        HSendPacket (i, NCMD_RETRANSMIT);
                    }
                    else
                    {
                        netbuffer.retransmitfrom = 0;
                        HSendPacket (i, 0);
                    }
                }
            GetPackets();
        }

    }



    //
    // CheckAbort
    //
    private void CheckAbort ()
    {
        event_t ev;
        int     stoptic;

        stoptic = TICK.GetTime () + 2; 
        while (TICK.GetTime() < stoptic) 
            VI.StartTic (); 

        VI.StartTic ();
        for ( ; eventtail != eventhead 
        ; eventtail = (++eventtail)&(MAXEVENTS-1) ) 
        { 
            ev = events[eventtail]; 
            if (ev.type == evtype_t.ev_keydown && ev.data1 == KEY_ESCAPE)
                I.Error ("Network game synchronization aborted.");
        } 
    }

    boolean[] gotinfo=new boolean[MAXNETNODES];

    /**
     * D_ArbitrateNetStart
     * @throws IOException 
     *
     * 
     */
    public void ArbitrateNetStart () throws IOException
    {
        int     i;
        autostart = true;

        // Clear it up...
        Arrays.fill(gotinfo,false);

        if (doomcom.consoleplayer!=0)
        {
            // listen for setup info from key player
            System.out.println("listening for network start info...\n");
            while (true)
            {
                CheckAbort ();
                if (!HGetPacket ())
                    continue;
                if (flags(netbuffer.checksum , NCMD_SETUP))
                {
                    if (netbuffer.player != VERSION)
                        I.Error ("Different DOOM versions cannot play a net game!");
                    startskill = skill_t.values()[netbuffer.retransmitfrom & 15];

                    // Deathmatch
                    if (((netbuffer.retransmitfrom & 0xc0) >> 6)==1) 
                        deathmatch = true;
                    else
                        // Cooperative
                        if (((netbuffer.retransmitfrom & 0xc0) >> 6)==2) 
                            altdeath = true;

                    nomonsters = (netbuffer.retransmitfrom & 0x20) > 0;
                    respawnparm = (netbuffer.retransmitfrom & 0x10) > 0;
                    startmap = netbuffer.starttic & 0x3f;
                    startepisode = netbuffer.starttic >> 6;
            return;
                }
            }
        }
        else
        {
            // key player, send the setup info
            System.out.println("sending network start info...\n");
            do
            {
                CheckAbort ();
                for (i=0 ; i<doomcom.numnodes ; i++)
                {
                    netbuffer.retransmitfrom = (byte) startskill.ordinal();
                    if (deathmatch)
                        netbuffer.retransmitfrom |= (1<<6);
                    else
                        if (altdeath)
                            netbuffer.retransmitfrom |= (2<<6);
                    if (nomonsters)
                        netbuffer.retransmitfrom |= 0x20;
                    if (respawnparm)
                        netbuffer.retransmitfrom |= 0x10;
                    netbuffer.starttic = (byte) (startepisode * 64 + startmap);
                    netbuffer.player = VERSION;
                    netbuffer.numtics = 0;
                    HSendPacket (i, NCMD_SETUP);
                }

                //#if 1
                for(i = 10 ; (i>0)  &&  HGetPacket(); --i)
                {
                    if((netbuffer.player&0x7f) < MAXNETNODES)
                        gotinfo[netbuffer.player&0x7f] = true;
                }
                /*
        while (HGetPacket ())
        {
        gotinfo[netbuffer.player&0x7f] = true;
        }
                 */

                for (i=1 ; i<doomcom.numnodes ; i++)
                    if (!gotinfo[i])
                        break;
            } while (i < doomcom.numnodes);
        }
    }

    //
    // D_CheckNetGame
    // Works out player numbers among the net participants
    //

    private void CheckNetGame () throws IOException
    {
        int             i;

        for (i=0 ; i<MAXNETNODES ; i++)
        {
            nodeingame[i] = false;
            nettics[i] = 0;
            remoteresend[i] = false;    // set when local needs tics
            resendto[i] = 0;        // which tic to start sending
        }

        // I_InitNetwork sets doomcom and netgame
        DNI.InitNetwork ();
        if (doomcom.id != DOOMCOM_ID)
            I.Error ("Doomcom buffer invalid!");

        // Maes: This is the only place where netbuffer is definitively set to something
        netbuffer = doomcom.data;
        consoleplayer = displayplayer = doomcom.consoleplayer;
        if (netgame)
            ArbitrateNetStart ();

        System.out.printf ("startskill %s  deathmatch: %s  startmap: %d  startepisode: %d\n",
            startskill.toString(), Boolean.toString(deathmatch), startmap, startepisode);

        // read values out of doomcom
        ticdup = doomcom.ticdup;
        // MAES: ticdup must not be zero at this point. Obvious, no?
        maxsend = BACKUPTICS/(2*ticdup)-1;
        if (maxsend<1)
            maxsend = 1;

        for (i=0 ; i<doomcom.numplayers ; i++)
            playeringame[i] = true;
        for (i=0 ; i<doomcom.numnodes ; i++)
            nodeingame[i] = true;

        System.out.printf ("player %d of %d (%d nodes)\n",(consoleplayer+1), doomcom.numplayers, doomcom.numnodes);

    }


    //
    // D_QuitNetGame
    // Called before quitting to leave a net game
    // without hanging the other players
    //
    @Override
    public void QuitNetGame () throws IOException
    {
        int             i, j;

        if (eval(debugfile))
            try {
                debugfile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (!netgame || !usergame || consoleplayer == -1 || demoplayback)
                return;

            // send a bunch of packets for security
            netbuffer.player = (byte) consoleplayer;
            netbuffer.numtics = 0;
            for (i=0 ; i<4 ; i++)
            {
                for (j=1 ; j<doomcom.numnodes ; j++)
                    if (nodeingame[j])
                        HSendPacket (j, NCMD_EXIT);
                I.WaitVBL (1);
            }
    }



    //
    // TryRunTics
    //
    int[] frametics=new int[4];
    int frameon;
    boolean[] frameskip=new boolean[4];
    int oldnettics;
    int  oldentertics;


    @Override
    public void TryRunTics () throws IOException
    {
        int     i;
        int     lowtic;
        int     entertic;

        int     realtics;
        int     availabletics;
        int     counts;
        int     numplaying;


        // get real tics        
        entertic = TICK.GetTime ()/ticdup;
        realtics = entertic - oldentertics;
        oldentertics = entertic;

        //System.out.printf("Entertic %d, realtics %d, oldentertics %d\n",entertic,realtics,oldentertics);

        // get available tics
        NetUpdate ();

        lowtic = MAXINT;
        numplaying = 0;
        for (i=0 ; i<doomcom.numnodes ; i++)
        {
            if (nodeingame[i])
            {
                numplaying++;
                if (nettics[i] < lowtic)
                    lowtic = nettics[i];
            }
        }
        availabletics = lowtic - gametic/ticdup;

        // decide how many tics to run
        if (realtics < availabletics-1)
            counts = realtics+1;
        else if (realtics < availabletics)
            counts = realtics;
        else
            counts = availabletics;

        if (counts < 1)
            counts = 1;

        frameon++;

        if (eval(debugfile)){
            sb.setLength(0);
            sb.append( "=======real: ");
            sb.append(realtics);
            sb.append("  avail: ");
            sb.append(availabletics);
            sb.append("  game: ");
            sb.append(counts);
            sb.append("\n");
            debugfile.write(sb.toString());
        }

        if (!demoplayback)
        {   
            // ideally nettics[0] should be 1 - 3 tics above lowtic
            // if we are consistantly slower, speed up time
            for (i=0 ; i<MAXPLAYERS ; i++)
                if (playeringame[i])
                    break;
            if (consoleplayer == i)
            {
                // the key player does not adapt
            }
            else
            {
                if (nettics[0] <= nettics[nodeforplayer[i]])
                {
                    gametime--;
                    System.out.print("-");
                }
                frameskip[frameon&3] = oldnettics > nettics[nodeforplayer[i]];
                oldnettics = nettics[0];
                if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
                {
                    skiptics = 1;
                    System.out.print("+");
                }
            }
        }// demoplayback

        // wait for new tics if needed
        while (lowtic < gametic/ticdup + counts)    
        {
            NetUpdate ();   
            lowtic = MAXINT;

            // Finds the node with the lowest number of tics.
            for (i=0 ; i<doomcom.numnodes ; i++)
                if (nodeingame[i] && nettics[i] < lowtic)
                    lowtic = nettics[i];

            if (lowtic < gametic/ticdup)
                I.Error ("TryRunTics: lowtic < gametic");

            // don't stay in here forever -- give the menu a chance to work
            int time=TICK.GetTime();
            if (time/ticdup - entertic >= 20)
            {
                M.Ticker ();
                return;
            }
        }

        // run the count * ticdup dics
        while (counts-->0)
        {
            for (i=0 ; i<ticdup ; i++)
            {
                if (gametic/ticdup > lowtic)
                    I.Error ("gametic>lowtic");
                if (advancedemo)
                    DM.DoAdvanceDemo ();
                M.Ticker ();
                Ticker ();
                gametic++;

                // modify command for duplicated tics
                if (i != ticdup-1)
                {
                    ticcmd_t    cmd;
                    int         buf;
                    int         j;

                    buf = (gametic/ticdup)%BACKUPTICS; 
                    for (j=0 ; j<MAXPLAYERS ; j++)
                    {
                        cmd = netcmds[j][buf];
                        cmd.chatchar = 0;
                        if (flags(cmd.buttons , BT_SPECIAL))
                            cmd.buttons = 0;
                    }
                }
            }
            NetUpdate ();   // check for new console commands
        }
    }


    @Override
    public doomcom_t getDoomCom() {
        return this.doomcom;
    }


    @Override
    public void setDoomCom(doomcom_t doomcom) {
        this.doomcom=doomcom;
    }


    @Override
    public void setGameAction(gameaction_t action) {
        this.gameaction=action;
    }


    @Override
    public gameaction_t getGameAction() {       
        return this.gameaction;
    }

    ////////////////////////////VIDEO SCALE STUFF ////////////////////////////////

    protected int SCREENWIDTH;
    protected int SCREENHEIGHT;
    protected int SAFE_SCALE;
    protected IVideoScale vs;



    @Override
    public void setVideoScale(IVideoScale vs) {
        this.vs=vs;
    }

    @Override
    public void initScaling() {
        this.SCREENHEIGHT=vs.getScreenHeight();
        this.SCREENWIDTH=vs.getScreenWidth();
        this.SAFE_SCALE=vs.getSafeScaling();
    }


    public void setCommandLineArgs(ICommandLineManager cM) {
        this.CM=cM;

    }


    public boolean shouldPollLockingKeys() {
        if (keysCleared) {
            keysCleared = false;
            return true;
        }
        return false;
    }
    
    /**
     * Since this is a fully OO implementation, we need a way to create
     * the instances of the Refresh daemon, the Playloop, the Wadloader 
     * etc. which however are now completely independent of each other
     * (well, ALMOST), and are typically only passed context when 
     * instantiated.
     * 
     *  If you instantiate one too early, it will have null context.
     *  
     *  The trick is to construct objects in the correct order. Some of
     *  them have Init() methods which are NOT yet safe to call.
     * 
     */

    public void Init(){
       
        // The various objects that need to "sense" the global status
        // end up here. This allows one-call updates.
        status_holders=new ArrayList<DoomStatusAware>();
        
        // Doommain is both "main" and handles most of the game status.
        this.DM=this;
        this.DG = this;
        this.DGN=this; // DoomMain also handles its own Game Networking.
             
        // Set ticker. It is a shared status object, but not a holder itself.
        if (eval(CM.CheckParm("-millis"))){

            TICK=new MilliTicker();
        }
        else if (eval(CM.CheckParm("-fasttic"))){
            TICK=new FastTicker();
        } else {
            TICK=new NanoTicker();
        }
        
        // Network "driver"
        status_holders.add((DoomStatusAware) (this.DNI=new DummyNetworkDriver(this)));
        
        // Random number generator, but we can have others too.
        this.RND=new DoomRandom();
        
        // Sound can be left until later, in Start

        this.W=new WadLoader(this.I); // The wadloader is a "weak" status holder.
        status_holders.add(this.WIPE=selectWiper());   

        // Then the menu...
        status_holders.add(this.HU=new HU(this));
        status_holders.add(this.M=new Menu(this));
        status_holders.add(this.LL=new BoomLevelLoader(this));
        
        // This will set R.
        this.R= selectRenderer();
        status_holders.add(this.R);
        status_holders.add((this.P=new Actions(this)));
        status_holders.add(this.ST=new StatusBar(this));
        status_holders.add(this.AM=selectAutoMap()); // Call Init later.
        // Let the renderer pick its own. It makes linking easier.
        this.TM=R.getTextureManager();
        this.SM=R.getSpriteManager();        

        //_D_: well, for EndLevel and Finale to work, they need to be instanciated somewhere!
        // it seems to fit perfectly here
        status_holders.add(this.WI = new EndLevel(this));    
        status_holders.add(this.F = selectFinale());
        
        // TODO: find out if we have requests for a specific resolution,
        // and try honouring them as closely as possible.       

        // 23/5/2011: Experimental dynamic resolution subsystem
        vs=VisualSettings.parse(CM);
        
        // Initializing actually sets drawing positions, constants,
        // etc. for main. Children will be set later in Start().
        this.initScaling();
        
        this.V=selectVideoRenderer();

        status_holders.add((DoomStatusAware) this.I);
        status_holders.add((DoomStatusAware) this.V);
        
        // Disk access visualizer
        
        status_holders.add((DoomStatusAware) (this.DD=new DiskDrawer(this,DiskDrawer.STDISK)));
        
        updateStatusHolders(this);


    }
    


    public static final class HiColor extends DoomMain<byte[], short[]>{
    
        public HiColor(){
            super();
        }
        
        protected IAutoMap<byte[], short[]> selectAutoMap() {
            return new Map.HiColor(this);
        }
        
        protected final Finale<byte[]> selectFinale(){
            return new Finale<byte[]>(this);
        }
        
        protected final DoomVideoRenderer<byte[],short[]> selectVideoRenderer(){
            return new BufferedRenderer16(SCREENWIDTH,SCREENHEIGHT);
        }
        
        protected final DoomVideoInterface<short[]> selectVideoInterface(){
            return new AWTDoom.HiColor(this,V);
        }
        
        protected final Wiper<byte[],short[]> selectWiper(){
            return new Wiper.HiColor(this);
        }
        
        protected final Renderer<byte[],short[]> selectRenderer() {
            // Serial or parallel renderer (serial is default, but can be forced)
            if (eval(CM.CheckParm("-serialrenderer"))){
                return new UnifiedRenderer.HiColor(this);    
            } else 
                // Parallel. Either with default values (2,1) or user-specified.
                if (CM.CheckParmBool("-parallelrenderer")||CM.CheckParmBool("-parallelrenderer2")){        
                    int p = CM.CheckParm ("-parallelrenderer");
                    if (p<1) p=CM.CheckParm("-parallelrenderer2");
                    
                    if (p < CM.getArgc()-1)
                    {
                        // Next THREE args must be numbers.
                        int walls=1, floors=1,masked=2;
                        startmap = Integer.parseInt(CM.getArgv(p+1));
                        // Try parsing walls.
                        try {
                            walls=Integer.parseInt(CM.getArgv(p+1));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }

                        // Try parsing floors. If wall succeeded, but floors
                        // not, it will default to 1.
                        try {
                            floors=Integer.parseInt(CM.getArgv(p+2));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }
                        
                        try {
                            masked=Integer.parseInt(CM.getArgv(p+3));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }

                        // In the worst case, we will use the defaults.
                        if  (CM.CheckParmBool("-parallelrenderer"))
                            // TODO: temporarily disabled
                        	return new ParallelRenderer.HiColor(this,walls,floors,masked);  
                       //     return (Renderer<byte[], short[]>) new ParallelRenderer(this,walls,floors,masked);
                       // else
                       //     return (Renderer<byte[], short[]>) new ParallelRenderer2(this,walls,floors,masked);
                    }
                } else {
                    // Force serial
                    return new UnifiedRenderer.HiColor(this);   
                }
            
            return null;
        }

        /**
        *  M_Screenshot
        *  
        *  Currently saves PCX screenshots, and only in devparm.
        *  Very oldschool ;-)
        *  
        *  TODO: add non-devparm hotkey for screenshots, sequential screenshot
        *  messages, option to save as either PCX or PNG. Also, request
        *  current palette from VI (otherwise gamma settings and palette effects
        *  don't show up).
        *  
        */

       public void ScreenShot ()
       {
           int     i;
           short[]  linear;
           String format=new String("DOOM%d%d%d%d.png");
           String lbmname = null;
           
           // munge planar buffer to linear
           linear = (short[]) V.getScreen(DoomVideoRenderer.SCREEN_WS);
           VI.ReadScreen (linear);

           // find a file name to save it to
           
           int[] digit=new int[4];
           
           for (i=0 ; i<=9999 ; i++)
           {
           digit[0] = ((i/1000 )%10);
           digit[1] =  ((i/100)%10);
           digit[2] =  ((i/10)%10);
           digit[3] =  (i%10);
           lbmname=String.format(format, digit[0],digit[1],digit[2],digit[3]);
           if (!C2JUtils.testReadAccess(lbmname))
               break;  // file doesn't exist
           }
           if (i==10000)
           I.Error ("M_ScreenShot: Couldn't create a PNG");

           // save the pcx file
           MenuMisc.WritePNGfile (lbmname, linear,
                 SCREENWIDTH, SCREENHEIGHT);

           players[consoleplayer].message = "screen shot";
       }

    }
    
    public static final class Indexed extends DoomMain<byte[], byte[]>{
        
        public Indexed(){
            super();
        }
        
        protected IAutoMap<byte[], byte[]> selectAutoMap() {
            return new Map.Indexed(this);
        }
        
        protected final Finale<byte[]> selectFinale(){
            return new Finale<byte[]>(this);
        }
        
        protected final DoomVideoRenderer<byte[],byte[]> selectVideoRenderer(){
            return new BufferedRenderer(SCREENWIDTH,SCREENHEIGHT);
        }
        
        protected final DoomVideoInterface<byte[]> selectVideoInterface(){
            return new AWTDoom.Indexed(this,V);
        }
        
        protected final Wiper<byte[],byte[]> selectWiper(){
            return new Wiper.Indexed(this);
        }        
        protected final Renderer<byte[],byte[]> selectRenderer() {
            // Serial or parallel renderer (serial is default, but can be forced)
            if (eval(CM.CheckParm("-serialrenderer"))){
                return new UnifiedRenderer.Indexed(this);    
            } else 
                // Parallel. Either with default values (2,1) or user-specified.
                if (CM.CheckParmBool("-parallelrenderer")||CM.CheckParmBool("-parallelrenderer2")){        
                    int p = CM.CheckParm ("-parallelrenderer");
                    if (p<1) p=CM.CheckParm("-parallelrenderer2");
                    
                    if (p < CM.getArgc()-1)
                    {
                        // Next THREE args must be numbers.
                        int walls=1, floors=1,masked=2;
                        startmap = Integer.parseInt(CM.getArgv(p+1));
                        // Try parsing walls.
                        try {
                            walls=Integer.parseInt(CM.getArgv(p+1));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }

                        // Try parsing floors. If wall succeeded, but floors
                        // not, it will default to 1.
                        try {
                            floors=Integer.parseInt(CM.getArgv(p+2));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }
                        
                        try {
                            masked=Integer.parseInt(CM.getArgv(p+3));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }

                        // In the worst case, we will use the defaults.
                        if  (CM.CheckParmBool("-parallelrenderer"))                            
                            // TODO: temporarily disabled
                            //return new UnifiedRenderer.Indexed(this);   
                            return new ParallelRenderer.Indexed(this,walls,floors,masked);
                        //else
                          //  return new ParallelRenderer2(this,walls,floors,masked);
                    }
                } else {
                    // Force serial
                    return new UnifiedRenderer.Indexed(this);   
                }
            
            return null;
        }

        /**
        *  M_Screenshot
        *  
        *  Currently saves PCX screenshots, and only in devparm.
        *  Very oldschool ;-)
        *  
        *  TODO: add non-devparm hotkey for screenshots, sequential screenshot
        *  messages, option to save as either PCX or PNG. Also, request
        *  current palette from VI (otherwise gamma settings and palette effects
        *  don't show up).
        *  
        */

       public void ScreenShot ()
       {
           int     i;
           byte[]  linear;
           String format=new String("DOOM%d%d%d%d.png");
           String lbmname = null;
           
           // munge planar buffer to linear
           linear = (byte[]) V.getScreen(DoomVideoRenderer.SCREEN_WS);
           VI.ReadScreen (linear);

           // find a file name to save it to
           
           int[] digit=new int[4];
           
           for (i=0 ; i<=9999 ; i++)
           {
           digit[0] = ((i/1000 )%10);
           digit[1] =  ((i/100)%10);
           digit[2] =  ((i/10)%10);
           digit[3] =  (i%10);
           lbmname=String.format(format, digit[0],digit[1],digit[2],digit[3]);
           if (!C2JUtils.testReadAccess(lbmname))
               break;  // file doesn't exist
           }
           if (i==10000)
           I.Error ("M_ScreenShot: Couldn't create a PNG");

           // save the pcx file
           MenuMisc.WritePNGfile(lbmname, linear,
                 SCREENWIDTH, SCREENHEIGHT,V.getPalette());

           players[consoleplayer].message = "screen shot";
       }
        
    }
 
    public static final class TrueColor extends DoomMain<byte[], int[]>{
        
        public TrueColor(){
            super();
        }
        
        protected IAutoMap<byte[], int[]> selectAutoMap() {
            return new Map.TrueColor(this);
        }
        
        protected final Finale<byte[]> selectFinale(){
            return new Finale<byte[]>(this);
        }
        
        protected final DoomVideoRenderer<byte[],int[]> selectVideoRenderer(){
            return new BufferedRenderer32(SCREENWIDTH,SCREENHEIGHT);
        }
        
        protected final DoomVideoInterface<int[]> selectVideoInterface(){
            return new AWTDoom.TrueColor(this,V);
        }
        
        protected final Wiper<byte[],int[]> selectWiper(){
            return new Wiper.TrueColor(this);
        }
        
        protected final Renderer<byte[],int[]> selectRenderer() {
            // Serial or parallel renderer (serial is default, but can be forced)
            if (eval(CM.CheckParm("-serialrenderer"))){
                return new UnifiedRenderer.TrueColor(this);    
            } else 
                // Parallel. Either with default values (2,1) or user-specified.
                if (CM.CheckParmBool("-parallelrenderer")||CM.CheckParmBool("-parallelrenderer2")){        
                    int p = CM.CheckParm ("-parallelrenderer");
                    if (p<1) p=CM.CheckParm("-parallelrenderer2");
                    
                    if (p < CM.getArgc()-1)
                    {
                        // Next THREE args must be numbers.
                        int walls=1, floors=1,masked=2;
                        startmap = Integer.parseInt(CM.getArgv(p+1));
                        // Try parsing walls.
                        try {
                            walls=Integer.parseInt(CM.getArgv(p+1));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }

                        // Try parsing floors. If wall succeeded, but floors
                        // not, it will default to 1.
                        try {
                            floors=Integer.parseInt(CM.getArgv(p+2));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }
                        
                        try {
                            masked=Integer.parseInt(CM.getArgv(p+3));
                        } catch (Exception e){
                            // OK, move on anyway.
                        }

                        // In the worst case, we will use the defaults.
                        if  (CM.CheckParmBool("-parallelrenderer"))
                            // TODO: temporarily disabled
                        	return new ParallelRenderer.TrueColor(this,walls,floors,masked);   
                       //     return (Renderer<byte[], short[]>) new ParallelRenderer(this,walls,floors,masked);
                       // else
                       //     return (Renderer<byte[], short[]>) new ParallelRenderer2(this,walls,floors,masked);
                    }
                } else {
                    // Force serial
                    return new UnifiedRenderer.TrueColor(this);   
                }
            
            return null;
        }

        /**
        *  M_Screenshot
        *  
        *  Currently saves PCX screenshots, and only in devparm.
        *  Very oldschool ;-)
        *  
        *  TODO: add non-devparm hotkey for screenshots, sequential screenshot
        *  messages, option to save as either PCX or PNG. Also, request
        *  current palette from VI (otherwise gamma settings and palette effects
        *  don't show up).
        *  
        */

       public void ScreenShot ()
       {
           int     i;
           int[]  linear;
           String format=new String("DOOM%d%d%d%d.png");
           String lbmname = null;
           
           // munge planar buffer to linear
           linear = (int[]) V.getScreen(DoomVideoRenderer.SCREEN_WS);
           VI.ReadScreen (linear);

           // find a file name to save it to
           
           int[] digit=new int[4];
           
           for (i=0 ; i<=9999 ; i++)
           {
           digit[0] = ((i/1000 )%10);
           digit[1] =  ((i/100)%10);
           digit[2] =  ((i/10)%10);
           digit[3] =  (i%10);
           lbmname=String.format(format, digit[0],digit[1],digit[2],digit[3]);
           if (!C2JUtils.testReadAccess(lbmname))
               break;  // file doesn't exist
           }
           if (i==10000)
           I.Error ("M_ScreenShot: Couldn't create a PNG");

           // save the pcx file
           MenuMisc.WritePNGfile (lbmname, linear,
                 SCREENWIDTH, SCREENHEIGHT);

           players[consoleplayer].message = "screen shot";
       }

    }
    
}

//$Log: DoomMain.java,v $
//Revision 1.110  2016/06/06 22:21:24  velktron
//Use coalescing
//
//Revision 1.109  2012/11/06 16:04:58  velktron
//Variables manager less tightly integrated.
//
//Revision 1.108  2012/11/05 17:25:29  velktron
//Fixed tinting system according to SodaHolic's advice.
//
//Revision 1.107  2012/09/27 16:53:46  velktron
//Stupid brokeness prevented -loadgame from working.
//
//Revision 1.106  2012/09/26 23:15:20  velktron
//Parallel renderer restored...sort of.
//
//Revision 1.105  2012/09/26 15:54:22  velktron
//Spritemanager is set up by renderer.
//
//Revision 1.104  2012/09/24 22:36:49  velktron
//Fixed HOM detection.
//
//Revision 1.103  2012/09/24 17:16:22  velktron
//Massive merge between HiColor and HEAD. There's no difference from now on, and development continues on HEAD.
//
//Revision 1.101.2.11  2012/09/24 16:58:06  velktron
//TrueColor, Generics.
//
//Revision 1.101.2.10  2012/09/21 16:17:25  velktron
//More generic.
//
//Revision 1.101.2.9  2012/09/20 14:25:13  velktron
//Unified DOOM!!!
//

package doom;

/** A shiny new and enterprisey (yeah right) interface for
 *  command-line handling. No more argv/argc nastiness!
 *  
 * @author velktron
 *
 */

public interface ICommandLineManager {

    public abstract String getArgv(int index);

    public abstract int getArgc();

    /**
     * M_CheckParm Checks for the given parameter in the program's command line
     * arguments. Returns the argument number (1 to argc-1) or 0 if not present
     * 
     * OK, now WHY ON EARTH was this be defined in m_menu.c?
     * 
     * MAES: this needs to be modified for Java, or else bump myargc one element up.
     * 
     */

    public abstract int CheckParm(String check);

    void FindResponseFile();

    public abstract void setArgv(int index, String string);

	boolean CheckParmBool(String check);

}
package doom;
import defines.*;

//
// PSPRITE ACTIONS for waepons.
// This struct controls the weapon animations.
//
// Each entry is:
//   ammo/amunition type
//  upstate
//  downstate
// readystate
// atkstate, i.e. attack/fire/hit frame
// flashstate, muzzle flash
//

public class weaponinfo_t {

    /*    
    public weaponinfo_t(ammotype_t ammo, int upstate, int downstate,
            int readystate, int atkstate, int flashstate) {
        super();
        this.ammo = ammo;
        this.upstate = upstate;
        this.downstate = downstate;
        this.readystate = readystate;
        this.atkstate = atkstate;
        this.flashstate = flashstate;
    }*/
        public ammotype_t  ammo;
             
        
        public weaponinfo_t(ammotype_t ammo, statenum_t upstate,
                statenum_t downstate, statenum_t readystate,
                statenum_t atkstate, statenum_t flashstate) {
            super();
            this.ammo = ammo;
            this.upstate = upstate;
            this.downstate = downstate;
            this.readystate = readystate;
            this.atkstate = atkstate;
            this.flashstate = flashstate;
        }
        
        public statenum_t     upstate;
        public statenum_t     downstate;
        public statenum_t     readystate;
        public statenum_t     atkstate;
        public statenum_t     flashstate;
        
        
        /*
        public int     upstate;
        public int     downstate;
        public int     readystate;
        public int     atkstate;
        public int     flashstate;
        */
    
}

package doom;

/** The possible events according to Doom */

public enum evtype_t {
        ev_null,
        ev_keydown,
        ev_keyup,
        ev_mouse,
        ev_joystick,
        ev_mousewheel, // extension
        ev_clear // Forcibly clear all button input (e.g. when losing focus)
    };

package doom;

/** Mocha Doom uses the think_t type as an ENUM for available action functions. This
 * makes enumerations etc. easy to keep track of.
 * 
 * @author velktron
 *
 */

public enum think_t {
    /** Here's your "decent NOP" function */
	NOP,
	A_Light0(2),
    A_WeaponReady(2),
    A_Lower(2),
    A_Raise(2),
    A_Punch(2),
    A_ReFire(2),
    A_FirePistol(2),
    A_Light1(2),
    A_FireShotgun(2),
    A_Light2(2),
    A_FireShotgun2(2),
    A_CheckReload(2),
    A_OpenShotgun2(2),
    A_LoadShotgun2(2),
    A_CloseShotgun2(2),
    A_FireCGun(2),
    A_GunFlash(2),
    A_FireMissile(2),
    A_Saw(2),
    A_FirePlasma(2),
    A_BFGsound(2),
    A_FireBFG(2),
    A_BFGSpray(1),
    A_Explode(1),
    A_Pain(1),
    A_PlayerScream(1),
    A_Fall(1),
    A_XScream(1),
    A_Look(1),
    A_Chase(1),
    A_FaceTarget(1),
    A_PosAttack(1),
    A_Scream(1),
    A_SPosAttack(1),
    A_VileChase(1),
    A_VileStart(1),
    A_VileTarget(1),
    A_VileAttack(1),
    A_StartFire(1),
    A_Fire(1),
    A_FireCrackle(1),
    A_Tracer(1),
    A_SkelWhoosh(1),
  //Historically, "think_t" is yet another
  //function pointer to a routine to handle
  //an actor.

  //
  //Experimental stuff.
  //To compile this as "ANSI C with classes"
  //we will need to handle the various
  //action functions cleanly.
  //
  //typedef  void (*actionf_v)();
  //typedef  void (*actionf_p1)( void* );
  //typedef  void (*actionf_p2)( void*, void* );

  /*typedef union
  {
  actionf_p1  acp1;
  actionf_v   acv;
  actionf_p2  acp2;

  } actionf_t;

  */

    A_SkelFist(1),
    A_SkelMissile(1),
    A_FatRaise(1),
    A_FatAttack1(1),
    A_FatAttack2(1),
    A_FatAttack3(1),
    A_BossDeath(1),
    A_CPosAttack(1),
    A_CPosRefire(1),
    A_TroopAttack(1),
    A_SargAttack(1),
    A_HeadAttack(1),
    A_BruisAttack(1),
    A_SkullAttack(1),
    A_Metal(1),
    A_SpidRefire(1),
    A_BabyMetal(1),
    A_BspiAttack(1),
    A_Hoof(1),
    A_CyberAttack(1),
    A_PainAttack(1),
    A_PainDie(1),
    A_KeenDie(1),
    A_BrainPain(1),
    A_BrainScream(1),
    A_BrainDie(1),
    A_BrainAwake(1),
    A_BrainSpit(1),
    A_SpawnSound(1),
    A_SpawnFly(1),
    A_BrainExplode(1),
    P_MobjThinker(1),
    T_FireFlicker(1),
	T_LightFlash(1),
	T_StrobeFlash(1),
	T_Glow(1),
	T_MoveCeiling(1),
	T_MoveFloor(1),
	T_VerticalDoor(1),
	T_PlatRaise(1), 
	T_SlidingDoor(1),
	// The following are dummies that exist only for demo sync debugging
	DeathMatchSpawnPlayer,
	PlayerInSpecialSector, 
	SpawnLightFlash, 
	SpawnStrobeFlash, 
	ExplodeMissile,
	CheckMissileRange,
	DoPlat,
	CheckMissileSpawn,
	DamageMobj, 
	KillMobj, 
	NewChaseDir, 
	P_GunShot, 
	PIT_ChangeSector, 
	PIT_CheckThing, 
	TryWalk, 
	SpawnBlood, 
	SpawnMapThing, 
	SpawnMobj, 
	SpawnMissile,
	SpawnPuff;
    
	
	think_t(){
	    type=0; // Default, but Doom has no "type 0" functions!
	}
	
    think_t(int type){
        this.type=type;
    }

    /** 0 for void, 1 for acp1, 2 for acp2 */
    public int getType() {
        return type;
    }

    private int type;
    
    public String ToString(){
        return this.name()+" Type: "+type;
    }
    
    public static final int acpv=0;
    public static final int acp1=1;
    public static final int acp2=2;
	
}

package doom;

import java.io.IOException;

/** Doom is actually tied to its networking module.
 *  Therefore, no matter where and how you implement it, these functions
 *  need to be callable from within many modules.
 *  
 *  This is the so called "game networking" which is internal and game-specific,
 *  and not system networking which deals with the low level sockets and packet 
 *  stuff. You'll need DoomSystemNetworking for that one.
 *  
 * @author Velktron
 *
 */

public interface IDoomGameNetworking {
	
	public void TryRunTics() throws IOException;
	
	/**
	 * NetUpdate
	 * Builds ticcmds for console player,
	 * sends out a packet
	 * @throws IOException 
	 */

	public void NetUpdate ();
	
	public doomcom_t getDoomCom();
	
	public void setDoomCom(doomcom_t doomcom);
	
	public int getTicdup();

	public void setTicdup(int ticdup);

}

package doom;

import i.DoomStatusAware;
import i.IDoomSystem;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

import m.IRandom;

import data.Tables;
import data.state_t;
import defines.*;
import data.sounds.sfxenum_t;
import static data.Defines.*;
import static data.Tables.*;
import static m.fixed_t.*;
import static data.info.*;
import static p.mobj_t.*;
import p.Actions;
import p.mobj_t;
import p.pspdef_t;
import rr.LightsAndColors;
import rr.Renderer;
import rr.sector_t;
import s.IDoomSound;
import utils.C2JUtils;
import w.DoomBuffer;
import w.DoomIO;
import w.IPackableDoomObject;
import w.IReadableDoomObject;
import static utils.C2JUtils.*;
import static data.Limits.*;
import static doom.items.weaponinfo;
import static p.mobj_t.MF_SHADOW;

/**
 * Extended player object info: player_t The player data structure depends on a
 * number of other structs: items (internal inventory), animation states
 * (closely tied to the sprites used to represent them, unfortunately). 
 * 
 * #include "d_items.h" 
 * #include "p_pspr.h" 
 * 
 * In addition, the player is just a special
 * case of the generic moving object/actor. 
 * NOTE: this doesn't mean it needs to extend it, although it would be
 * possible.
 * 
 * #include "p_mobj.h" 
 * 
 * Finally, for odd reasons, the player input is buffered within 
 * the player data struct, as  commands per game tick. 
 * 
 * #include "d_ticcmd.h"
 */

public class player_t /*extends mobj_t */
        implements Cloneable ,DoomStatusAware, IReadableDoomObject, IPackableDoomObject
        {
	
    /** Probably doomguy needs to know what the fuck is going on */
    private DoomStatus DS;
    private IDoomGame DG;
    private Actions P;
    private Renderer<?,?> R;
    private IRandom RND;
    private IDoomSystem I;
    private IDoomSound S;
	
    /* Fugly hack to "reset" the player. Not worth the fugliness.
    public static player_t nullplayer;
    static {
        nullplayer = new player_t();
    }
    */

    public player_t() {
        powers = new int[NUMPOWERS];
        frags = new int[MAXPLAYERS];
        ammo = new int[NUMAMMO];
        //maxammo = new int[NUMAMMO];
        maxammo= new int[NUMAMMO];
        cards = new boolean[card_t.NUMCARDS.ordinal()];
        weaponowned = new boolean[NUMWEAPONS];
        psprites = new pspdef_t[NUMPSPRITES];
        C2JUtils.initArrayOfObjects(psprites);
        this.mo=new mobj_t();
        // If a player doesn't reference himself through his object, he will have an existential crisis.
        this.mo.player=this;
        readyweapon=weapontype_t.wp_fist;
        this.cmd=new ticcmd_t();
        //weaponinfo=new weaponinfo_t();
    }

    public final static int CF_NOCLIP = 1; // No damage, no health loss.

    public final static int CF_GODMODE = 2;

    public final static int CF_NOMOMENTUM = 4; // Not really a cheat, just a debug aid.

    
    /** The "mobj state" of the player is stored here, even though he "inherits"
     *  all mobj_t properties (except being a thinker). However, for good or bad,
     *  his mobj properties are modified by accessing player.mo
     */
    public mobj_t mo;

    /** playerstate_t */
    public int playerstate;

    public ticcmd_t cmd;

    /**
     * Determine POV, including viewpoint bobbing during movement. (fixed_t)
     * Focal origin above r.z
     */
    public int viewz;
    
    /** (fixed_t) Base height above floor for viewz. */
    public int viewheight;

    /** (fixed_t) Bob/squat speed. */
    public int deltaviewheight;

    /** (fixed_t) bounded/scaled total momentum. */
    public int bob;

    // Heretic stuff
	public int			flyheight;
	public int			lookdir;
	public boolean		centering;
    
    /**
     * This is only used between levels, mo->health is used during levels.
     * CORRECTION: this is also used by the automap widget.
     * MAES: fugly hax, as even passing "Integers" won't work, as they are immutable.
     * Fuck that, I'm doing it the fugly MPI Java way!
     */
    public int[] health = new int[1];

    /** has to be passed around :-( */
    public int[] armorpoints = new int[1];

    /** Armor type is 0-2. */
    public int armortype;

    /** Power ups. invinc and invis are tic counters. */
    public int[] powers;

    public boolean[] cards;

    public boolean backpack;

    // Frags, kills of other players.
    public int[] frags;

    public weapontype_t readyweapon;

    // Is wp_nochange if not changing.
    public weapontype_t pendingweapon;

    public boolean[] weaponowned;

    public int[] ammo;

    public int[] maxammo;

    /** True if button down last tic. */
    public boolean attackdown;

    public boolean usedown;

    // Bit flags, for cheats and debug.
    // See cheat_t, above.
    public int cheats;

    // Refired shots are less accurate.
    public int refire;

    // For intermission stats.
    public int killcount;

    public int itemcount;

    public int secretcount;

    // Hint messages.
    public String message;

    // For screen flashing (red or bright).
    public int damagecount;

    public int bonuscount;

    // Who did damage (NULL for floors/ceilings).
    public mobj_t attacker;

    // So gun flashes light up areas.
    public int extralight;

    /**
     * Current PLAYPAL, ??? can be set to REDCOLORMAP for pain, etc. MAES: "int"
     * my ass. It's yet another pointer alias into colormaps. Ergo, array and
     * pointer.
     */

    // public byte[] fixedcolormap;
    public int fixedcolormap;

    // Player skin colorshift,
    // 0-3 for which color to draw player.
    public int colormap;

    // TODO: Overlay view sprites (gun, etc).
    public pspdef_t[] psprites;

    // True if secret level has been done.
    public boolean didsecret;

    /** It's probably faster to clone the null player */

    public void reset() {

        Arrays.fill(this.ammo, 0);
        Arrays.fill(this.armorpoints, 0);
        Arrays.fill(this.cards, false);
        Arrays.fill(this.frags, 0);
        Arrays.fill(this.health, 0);
        Arrays.fill(this.maxammo, 0);
        Arrays.fill(this.powers, 0);
        Arrays.fill(this.weaponowned, false);
        //Arrays.fill(this.psprites, null);
        this.cheats=0; // Forgot to clear up cheats flag...
        this.armortype = 0;
        this.attackdown = false;
        this.attacker = null;
        this.backpack = false;
        this.bob = 0;

    }

    @Override
    public player_t clone()
            throws CloneNotSupportedException {
        return (player_t) super.clone();
    }
        
    /** 16 pixels of bob */
    private static int MAXBOB = 0x100000;

    /**
     * P_Thrust Moves the given origin along a given angle.
     * 
     * @param angle
     *        (angle_t)
     * @param move
     *        (fixed_t)
     */

    public void Thrust(long angle, int move) {
        mo.momx += FixedMul(move, finecosine(angle));
        mo.momy += FixedMul(move, finesine( angle));
    }

    protected final static int PLAYERTHRUST=2048/TIC_MUL;
    
    /**
     * P_MovePlayer
     */
    public void MovePlayer() {
        ticcmd_t cmd = this.cmd;

        mo.angle += (cmd.angleturn << 16);
        mo.angle&=BITS32;
        
        // Do not let the player control movement
        // if not onground.
        onground = (mo.z <= mo.floorz);

        if (cmd.forwardmove != 0 && onground)
            Thrust(mo.angle, cmd.forwardmove * PLAYERTHRUST);

        if (cmd.sidemove != 0 && onground)
            Thrust((mo.angle - ANG90)&BITS32, cmd.sidemove * PLAYERTHRUST);

        if ((cmd.forwardmove != 0 || cmd.sidemove != 0)
                && mo.state == states[statenum_t.S_PLAY.ordinal()]) {
            this.mo.SetMobjState(statenum_t.S_PLAY_RUN1);
        }
        
        // Freelook code ripped off Heretic. Sieg heil!
        
        int look = cmd.lookfly&15;
        
    	if(look > 7)
    	{
    		look -= 16;
    	}
    	if(look!=0)
    	{
    		if(look == TOCENTER)
    		{
    			centering = true;
    		}
    		else
    		{
    			lookdir += 5*look;
    			if(lookdir > 90 || lookdir < -110)
    			{
    				lookdir -= 5*look;
    			}
    		}
    	}
    	
    	// Centering is done over several tics
    	if(centering)
    	{
    		if(lookdir > 0)
    		{
    			lookdir -= 8;
    		}
    		else if(lookdir < 0)
    		{
    			lookdir += 8;
    		}
    		if(Math.abs(lookdir) < 8)
    		{
    			lookdir = 0;
    			centering = false;
    		}
    	}
    	/* Flight stuff from Heretic
    	fly = cmd.lookfly>>4;
    		
    	if(fly > 7)
    	{
    		fly -= 16;
    	}
    	if(fly && player->powers[pw_flight])
    	{
    		if(fly != TOCENTER)
    		{
    			player->flyheight = fly*2;
    			if(!(player->mo->flags2&MF2_FLY))
    			{
    				player->mo->flags2 |= MF2_FLY;
    				player->mo->flags |= MF_NOGRAVITY;
    			}
    		}
    		else
    		{
    			player->mo->flags2 &= ~MF2_FLY;
    			player->mo->flags &= ~MF_NOGRAVITY;
    		}
    	}
    	else if(fly > 0)
    	{
    		P_PlayerUseArtifact(player, arti_fly);
    	}
    	if(player->mo->flags2&MF2_FLY)
    	{
    		player->mo->momz = player->flyheight*FRACUNIT;
    		if(player->flyheight)
    		{
    			player->flyheight /= 2;
    		}
    	} */
    }


    //
    // GET STUFF
    //

    
    // a weapon is found with two clip loads,
    // a big item has five clip loads
    
    public static final int[] clipammo = { 10, 4, 20, 1 };

    /**
     * P_GiveAmmo Num is the number of clip loads, not the individual count (0=
     * 1/2 clip).
     * 
     * @return false if the ammo can't be picked up at all
     * @param ammo
     *        intended to be ammotype_t.
     */
        
    public boolean GiveAmmo(ammotype_t amm, int num) {
        int oldammo;
        int ammo = amm.ordinal();
        if (ammo == ammotype_t.am_noammo.ordinal())
            return false;

        if (ammo < 0 || ammo > NUMAMMO)
            I.Error("P_GiveAmmo: bad type %i", ammo);

        if (this.ammo[ammo] == maxammo[ammo])
            return false;

        if (num != 0)
            num *= clipammo[ammo];
        else
            num = clipammo[ammo] / 2;

        if (DS.gameskill == skill_t.sk_baby
                ||DS.gameskill == skill_t.sk_nightmare) {
            // give double ammo in trainer mode,
            // you'll need in nightmare
            num <<= 1;
        }

        oldammo = this.ammo[ammo];
        this.ammo[ammo] += num;

        if (this.ammo[ammo] > maxammo[ammo])
            this.ammo[ammo] = maxammo[ammo];

        // If non zero ammo,
        // don't change up weapons,
        // player was lower on purpose.
        if (oldammo != 0)
            return true;

        // We were down to zero,
        // so select a new weapon.
        // Preferences are not user selectable.
        switch (ammotype_t.values()[ammo]) {
        case am_clip:
            if (readyweapon == weapontype_t.wp_fist) {
                if (weaponowned[weapontype_t.wp_chaingun.ordinal()])
                    pendingweapon = weapontype_t.wp_chaingun;
                else
                    pendingweapon = weapontype_t.wp_pistol;
            }
            break;

        case am_shell:
            if (readyweapon == weapontype_t.wp_fist
                    || readyweapon == weapontype_t.wp_pistol) {
                if (weaponowned[weapontype_t.wp_shotgun.ordinal()])
                    pendingweapon = weapontype_t.wp_shotgun;
            }
            break;

        case am_cell:
            if (readyweapon == weapontype_t.wp_fist
                    || readyweapon == weapontype_t.wp_pistol) {
                if (weaponowned[weapontype_t.wp_plasma.ordinal()])
                    pendingweapon = weapontype_t.wp_plasma;
            }
            break;

        case am_misl:
            if (readyweapon == weapontype_t.wp_fist) {
                if (weaponowned[weapontype_t.wp_missile.ordinal()])
                    pendingweapon = weapontype_t.wp_missile;
            }
        default:
            break;
        }

        return true;
    }

    public static final int BONUSADD = 6;

    /**
     * P_GiveWeapon
     * The weapon name may have a MF_DROPPED flag ored in.
     */
    
    public boolean GiveWeapon(weapontype_t weapn, boolean dropped) {
        boolean gaveammo;
        boolean gaveweapon;
        int weapon = weapn.ordinal();

        if (DS.netgame && (DS.deathmatch != true) // ???? was "2"
                && !dropped) {
            // leave placed weapons forever on net games
            if (weaponowned[weapon])
                return false;

            bonuscount += BONUSADD;
            weaponowned[weapon] = true;

            if (DS.deathmatch)
                GiveAmmo(weaponinfo[weapon].ammo, 5);
            else
                GiveAmmo(weaponinfo[weapon].ammo, 2);
            pendingweapon = weapn;

            if (this ==DS.players[DS.consoleplayer])
                S.StartSound (null, sfxenum_t.sfx_wpnup);
                return false;
        }

        if (weaponinfo[weapon].ammo != ammotype_t.am_noammo) {
            // give one clip with a dropped weapon,
            // two clips with a found weapon
            if (dropped)
                gaveammo = GiveAmmo(weaponinfo[weapon].ammo, 1);
            else
                gaveammo = GiveAmmo(weaponinfo[weapon].ammo, 2);
        } else
            gaveammo = false;

        if (weaponowned[weapon])
            gaveweapon = false;
        else {
            gaveweapon = true;
            weaponowned[weapon] = true;
            pendingweapon = weapn;
        }

        return (gaveweapon || gaveammo);
    }

    /**
     * P_GiveBody Returns false if the body isn't needed at all
     */

    public boolean GiveBody(int num) {
        if (this.health[0] >= MAXHEALTH)
            return false;

        health[0] += num;
        if (health[0] > MAXHEALTH)
            health[0] = MAXHEALTH;
        mo.health = health[0];

        return true;
    }

    /**
     * P_GiveArmor Returns false if the armor is worse than the current armor.
     */

    public boolean GiveArmor(int armortype) {
        int hits;

        hits = armortype * 100;
        if (armorpoints[0] >= hits)
            return false; // don't pick up

        this.armortype = armortype;
        armorpoints[0] = hits;

        return true;
    }

    /**
     * P_GiveCard
     */
    
    public void GiveCard(card_t crd) {
        int card = crd.ordinal();
        if (cards[card])
            return;

        bonuscount = BONUSADD;
        cards[card] = true;
    }

    //
    // P_GivePower
    //
    public boolean GivePower( int /* powertype_t */power) // MAES:
                                                                          // I
                                                                          // didn't
                                                                          // change
                                                                          // this!
    {
        if (power == pw_invulnerability) {
            powers[power] = INVULNTICS;
            return true;
        }

        if (power == pw_invisibility) {
            powers[power] = INVISTICS;
            mo.flags |= MF_SHADOW;
            return true;
        }

        if (power == pw_infrared) {
            powers[power] = INFRATICS;
            return true;
        }

        if (power == pw_ironfeet) {
            powers[power] = IRONTICS;
            return true;
        }

        if (power == pw_strength) {
            GiveBody(100);
            powers[power] = 1;
            return true;
        }

        if (powers[power] != 0)
            return false; // already got it

        powers[power] = 1;
        return true;
    }
 
    /**
     * G_PlayerFinishLevel
     * Called when a player completes a level.
     */

    public final void PlayerFinishLevel () 
    { 
        Arrays.fill(powers, 0);
        Arrays.fill(cards,false);       
        mo.flags &= ~mobj_t.MF_SHADOW;     // cancel invisibility 
        extralight = 0;          // cancel gun flashes 
        fixedcolormap = 0;       // cancel ir gogles 
        damagecount = 0;         // no palette changes 
        bonuscount = 0;
        lookdir = 0; // From heretic
    } 
    

    /**
     * P_PlayerInSpecialSector
     * Called every tic frame
     *  that the player origin is in a special sector
     */
    
    protected void PlayerInSpecialSector ()
    {
        sector_t   sector;
        
        sector = mo.subsector.sector;

        // Falling, not all the way down yet?
        if (mo.z != sector.floorheight)
        return; 

        // Has hitten ground.
        switch (sector.special)
        {
          case 5:
        // HELLSLIME DAMAGE
        if (powers[pw_ironfeet]==0)
            if (!flags(DS.leveltime,0x1f))
                P.DamageMobj (mo,null, null, 10);
        break;
        
          case 7:
        // NUKAGE DAMAGE
        if (powers[pw_ironfeet]==0)
            if (!flags(DS.leveltime,0x1f))
                P.DamageMobj (mo, null, null, 5);
        break;
        
          case 16:
        // SUPER HELLSLIME DAMAGE
          case 4:
        // STROBE HURT
        if (!eval(powers[pw_ironfeet])
            || (RND.P_Random()<5) )
        {
            if (!flags(DS.leveltime,0x1f))
            P.DamageMobj (mo, null, null, 20);
        }
        break;
                
          case 9:
        // SECRET SECTOR
        secretcount++;
        sector.special = 0;
        break;
                
          case 11:
        // EXIT SUPER DAMAGE! (for E1M8 finale)
        cheats &= ~CF_GODMODE;

        if (!flags(DS.leveltime,0x1f))
            P.DamageMobj (mo, null, null, 20);

        if (health[0] <= 10)
            DG.ExitLevel();
        break;
                
          default:
        I.Error ("P_PlayerInSpecialSector: unknown special %d", sector.special);
        break;
        };
    }    
   
 // Index of the special effects (INVUL inverse) map.
public static final int INVERSECOLORMAP		=LightsAndColors.LIGHTLEVELS;
    

 
 //
//P_CalcHeight
//Calculate the walking / running height adjustment
//
public void CalcHeight () 
{
  int     angle;
  int bob; // fixed
  
  // Regular movement bobbing
  // (needs to be calculated for gun swing
  // even if not on ground)
  // OPTIMIZE: tablify angle
  // Note: a LUT allows for effects
  //  like a ramp with low health.
  this.bob =
  FixedMul (mo.momx, mo.momx)
  + FixedMul (mo.momy,mo.momy);
  
  this.bob >>= 2;

        
  if (this.bob>MAXBOB)
	  this.bob = MAXBOB;

  
  
  if (flags(cheats ,CF_NOMOMENTUM) || !onground)
  {
  viewz = mo.z + VIEWHEIGHT;

  if (viewz > mo.ceilingz-4*FRACUNIT)
      viewz = mo.ceilingz-4*FRACUNIT;

  viewz = mo.z + viewheight;
  return;
  }
      
  angle = (FINEANGLES/20*DS.leveltime)&FINEMASK;
  bob = FixedMul ( this.bob/2, finesine[angle]);

  
  // move viewheight
  if (playerstate == PST_LIVE)
  {
  viewheight += deltaviewheight;

  if (viewheight > VIEWHEIGHT)
  {
      viewheight = VIEWHEIGHT;
      deltaviewheight = 0;
  }

  if (viewheight < VIEWHEIGHT/2)
  {
      viewheight = VIEWHEIGHT/2;
      if (deltaviewheight <= 0)
      deltaviewheight = 1;
  }
  
  if (deltaviewheight!=0)    
  {
      deltaviewheight += FRACUNIT/4;
      if (deltaviewheight==0)
      deltaviewheight = 1;
  }
  }
  viewz = mo.z + viewheight + bob;

  if (viewz > mo.ceilingz-4*FRACUNIT)
  viewz = mo.ceilingz-4*FRACUNIT;
} 
 
 private static final long ANG5   = (ANG90/18);

 /**
  * P_DeathThink
  * Fall on your face when dying.
  * Decrease POV height to floor height.
  * 
  * DOOMGUY IS SO AWESOME THAT HE THINKS EVEN WHEN DEAD!!!
  * 
  */

 
public void DeathThink ()
{
  long     angle; //angle_t
  long     delta;

  MovePsprites ();
  
  // fall to the ground
  if (viewheight > 6*FRACUNIT)
  viewheight -= FRACUNIT;

  if (viewheight < 6*FRACUNIT)
  viewheight = 6*FRACUNIT;

  deltaviewheight = 0;
  onground = (mo.z <= mo.floorz);
  CalcHeight ();
  
  if (attacker!=null && attacker != mo)
  {
  angle = R.PointToAngle2 (mo.x,
               mo.y,
               attacker.x,
               attacker.y);
  
  delta = Tables.addAngles(angle, - mo.angle);
  
  if (delta < ANG5 || delta > -ANG5)
  {
      // Looking at killer,
      //  so fade damage flash down.
      mo.angle = angle;

      if (damagecount!=0)
      damagecount--;
  }
  else if (delta < ANG180)
      mo.angle += ANG5;
  else
      mo.angle -= ANG5;
  }
  else if (damagecount!=0)
  damagecount--;
  

  if (flags(cmd.buttons ,BT_USE))
  playerstate = PST_REBORN;
}
 
//
// P_MovePsprites
// Called every tic by player thinking routine.
//
public void MovePsprites () 
{

    pspdef_t    psp;
    @SuppressWarnings("unused") // Shut up compiler
	state_t state=null;    
 
    for (int i=0 ; i<NUMPSPRITES ; i++)
    {
    	   psp = psprites[i];
    // a null state means not active
    if ( (state = psp.state)!=null )  
    {
        // drop tic count and possibly change state

        // a -1 tic count never changes
        if (psp.tics != -1) 
        {
        psp.tics--;
        if (!eval(psp.tics))
            this.SetPsprite (i, psp.state.nextstate);
        }               
    }
    }
    
    psprites[ps_flash].sx = psprites[ps_weapon].sx;
    psprites[ps_flash].sy = psprites[ps_weapon].sy;
}

/**
/* P_SetPsprite
*/

public void
SetPsprite
( int       position,
  statenum_t    newstate ) 
{
    pspdef_t    psp;
    state_t state;
    
    psp = psprites[position];
    
    do
    {
    if (newstate==null)
    {
        // object removed itself
        psp.state = null;
        break;  
    }
    
    state = states[newstate.ordinal()];
    psp.state = state;
    psp.tics = (int) state.tics;    // could be 0

    if (state.misc1!=0)
    {
        // coordinate set
        psp.sx = (int) (state.misc1 << FRACBITS);
        psp.sy = (int) (state.misc2 << FRACBITS);
    }
    
    // Call action routine.
    // Modified handling.
    if (state.acp2!=null)
    {
        state.acp2.invoke(this, psp);
        if (psp.state==null)
        break;
    }
    
    newstate = psp.state.nextstate;
    
    } while (psp.tics==0);
    // an initial state of 0 could cycle through
}


    /** Accessory method to identify which "doomguy" we are.
     *  Because we can't use the [target.player-players] syntax
     *  in order to get an array index, in Java.
     *  
     *  If -1 is returned, then we have existential problems.
     *
     */    
    
    public int identify(){
        
        
        if (id>=0) return id;
        int i;    
        // Let's assume that we know jack.
            for (i=0;i<DS.players.length;i++)
                if (this==DS.players[i]) break;
            
            return id=i;
        
    }
    
    private int id=-1;
    
    private boolean onground;


        	
    /* psprnum_t enum */
    public static int ps_weapon=0,
        ps_flash=1,
        NUMPSPRITES=2;  
    
    public static int  LOWERSPEED  =   MAPFRACUNIT*6;
    public static int  RAISESPEED  =   MAPFRACUNIT*6;

    public static int  WEAPONBOTTOM    =128*FRACUNIT;
    public static int  WEAPONTOP       =32*FRACUNIT;


    // plasma cells for a bfg attack
    private static int  BFGCELLS        =40;        


    /*
     P_SetPsprite
    
    
    public void
    SetPsprite
    ( player_t  player,
      int       position,
      statenum_t    newstate ) 
    {
        pspdef_t    psp;
        state_t state;
        
        psp = psprites[position];
        
        do
        {
        if (newstate==null)
        {
            // object removed itself
            psp.state = null;
            break;  
        }
        
        state = states[newstate.ordinal()];
        psp.state = state;
        psp.tics = (int) state.tics;    // could be 0

        if (state.misc1!=0)
        {
            // coordinate set
            psp.sx = (int) (state.misc1 << FRACBITS);
            psp.sy = (int) (state.misc2 << FRACBITS);
        }
        
        // Call action routine.
        // Modified handling.
        if (state.action.getType()==acp2)
        {
            P.A.dispatch(state.action,this, psp);
            if (psp.state==null)
            break;
        }
        
        newstate = psp.state.nextstate;
        
        } while (psp.tics==0);
        // an initial state of 0 could cycle through
    }
    */
    
    /** fixed_t */
    int     swingx, swingy;

    /**P_CalcSwing
     * 
     * @param player
     */
    public void CalcSwing (player_t   player)
    {
        int swing; // fixed_t
        int     angle;
        
        // OPTIMIZE: tablify this.
        // A LUT would allow for different modes,
        //  and add flexibility.

        swing = this.bob;

        angle = (FINEANGLES/70*DS.leveltime)&FINEMASK;
        swingx = FixedMul ( swing, finesine[angle]);

        angle = (FINEANGLES/70*DS.leveltime+FINEANGLES/2)&FINEMASK;
        swingy = -FixedMul ( swingx, finesine[angle]);
    }



    //
    // P_BringUpWeapon
    // Starts bringing the pending weapon up
    // from the bottom of the screen.
    // Uses player
    //
    public void BringUpWeapon ()
    {
        statenum_t  newstate=statenum_t.S_NULL;
        
        if (pendingweapon == weapontype_t.wp_nochange)
        pendingweapon = readyweapon;
            
        if (pendingweapon == weapontype_t.wp_chainsaw)
        S.StartSound (mo, sfxenum_t.sfx_sawup);
            
        newstate = weaponinfo[pendingweapon.ordinal()].upstate;

        pendingweapon = weapontype_t.wp_nochange;
        psprites[ps_weapon].sy = WEAPONBOTTOM;

        this.SetPsprite ( ps_weapon, newstate);
    }

    /**
     * P_CheckAmmo
     * Returns true if there is enough ammo to shoot.
     * If not, selects the next weapon to use.
     */
    
    public boolean CheckAmmo ()
    {
        ammotype_t      ammo;
        int         count;

        ammo = weaponinfo[readyweapon.ordinal()].ammo;

        // Minimal amount for one shot varies.
        if (readyweapon == weapontype_t.wp_bfg)
        count = BFGCELLS;
        else if (readyweapon == weapontype_t.wp_supershotgun)
        count = 2;  // Double barrel.
        else
        count = 1;  // Regular.

        // Some do not need ammunition anyway.
        // Return if current ammunition sufficient.
        if (ammo == ammotype_t.am_noammo || this.ammo[ammo.ordinal()] >= count)
        return true;
            
        // Out of ammo, pick a weapon to change to.
        // Preferences are set here.
        do
        {
        if (weaponowned[weapontype_t.wp_plasma.ordinal()]
            && (this.ammo[ammotype_t.am_cell.ordinal()]!=0)
            && !DS.isShareware() )
        {
            pendingweapon = weapontype_t.wp_plasma;
        }
        else if (weaponowned[weapontype_t.wp_supershotgun.ordinal()] 
             && this.ammo[ammotype_t.am_shell.ordinal()]>2
             && DS.isCommercial() )
        {
            pendingweapon = weapontype_t.wp_supershotgun;
        }
        else if (weaponowned[weapontype_t.wp_chaingun.ordinal()]
             && this.ammo[ammotype_t.am_clip.ordinal()]!=0)
        {
            pendingweapon = weapontype_t.wp_chaingun;
        }
        else if (weaponowned[weapontype_t.wp_shotgun.ordinal()]
             && this.ammo[ammotype_t.am_shell.ordinal()]!=0)
        {
            pendingweapon = weapontype_t.wp_shotgun;
        }
        else if (this.ammo[ammotype_t.am_clip.ordinal()]!=0)
        {
            pendingweapon = weapontype_t.wp_pistol;
        }
        else if (weaponowned[weapontype_t.wp_chainsaw.ordinal()])
        {
            pendingweapon = weapontype_t.wp_chainsaw;
        }
        else if (weaponowned[weapontype_t.wp_missile.ordinal()]
             && this.ammo[ammotype_t.am_misl.ordinal()]!=0)
        {
            pendingweapon = weapontype_t.wp_missile;
        }
        else if (weaponowned[weapontype_t.wp_bfg.ordinal()]
             && this.ammo[ammotype_t.am_cell.ordinal()]>40
             && !DS.isShareware() )
        {
            pendingweapon = weapontype_t.wp_bfg;
        }
        else
        {
            // If everything fails.
            pendingweapon = weapontype_t.wp_fist;
        }
        
        } while (pendingweapon == weapontype_t.wp_nochange);

        // Now set appropriate weapon overlay.
        this.SetPsprite (
              ps_weapon,
              weaponinfo[readyweapon.ordinal()].downstate);

        return false;   
    }


    /**
     * P_DropWeapon
     * Player died, so put the weapon away.
     */
    
    public void DropWeapon ()
    {
        this.SetPsprite (
              ps_weapon,
              weaponinfo[readyweapon.ordinal()].downstate);
    }

    /**
     * P_SetupPsprites
     * Called at start of level for each 
     */
    
    public void SetupPsprites () 
    {
        int i;
        
        // remove all psprites
        for (i=0 ; i<NUMPSPRITES ; i++)
        psprites[i].state = null;
            
        // spawn the gun
        pendingweapon = readyweapon;
        BringUpWeapon ();
    }
    
    /**
     *  P_PlayerThink
     */
    public void PlayerThink (player_t player)
    {
     ticcmd_t       cmd;
     weapontype_t    newweapon;
     
     // fixme: do this in the cheat code
     if (flags(player.cheats , player_t.CF_NOCLIP))
     player.mo.flags |= MF_NOCLIP;
     else
     player.mo.flags &= ~MF_NOCLIP;
     
     // chain saw run forward
     cmd = player.cmd;
     if (flags(player.mo.flags , MF_JUSTATTACKED))
     {
     cmd.angleturn = 0;
     cmd.forwardmove = (0xc800/512);
     cmd.sidemove = 0;
     player.mo.flags &= ~MF_JUSTATTACKED;
     }
             
     
     if (player.playerstate == PST_DEAD)
     {
     player.DeathThink ();
     return;
     }
     
     // Move around.
     // Reactiontime is used to prevent movement
     //  for a bit after a teleport.
     if (eval(player.mo.reactiontime))
     player.mo.reactiontime--;
     else
         player.MovePlayer ();
     
         player.CalcHeight ();

     if (eval(player.mo.subsector.sector.special))
         player.PlayerInSpecialSector ();
     
     // Check for weapon change.

     // A special event has no other buttons.
     if (flags(cmd.buttons , BT_SPECIAL))
     cmd.buttons = 0;           
         
     if (flags(cmd.buttons , BT_CHANGE))
     {
     // The actual changing of the weapon is done
     //  when the weapon psprite can do it
     //  (read: not in the middle of an attack).
    // System.out.println("Weapon change detected, attempting to perform");
         
     newweapon = weapontype_t.values()[(cmd.buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT];

     // If chainsaw is available, it won't change back to the fist 
     // unless player also has berserk.
     if (newweapon == weapontype_t.wp_fist
         && player.weaponowned[weapontype_t.wp_chainsaw.ordinal()]
         && !(player.readyweapon == weapontype_t.wp_chainsaw
          && eval(player.powers[pw_strength])))
     {
         newweapon = weapontype_t.wp_chainsaw;
     }
     
     // Will switch between SG and SSG in Doom 2.
     
     if ( DS.isCommercial()
         && newweapon == weapontype_t.wp_shotgun 
         && player.weaponowned[weapontype_t.wp_supershotgun.ordinal()]
         && player.readyweapon != weapontype_t.wp_supershotgun)
     {
         newweapon = weapontype_t.wp_supershotgun;
     }
     

     if (player.weaponowned[newweapon.ordinal()]
         && newweapon != player.readyweapon)
     {
         // Do not go to plasma or BFG in shareware,
         //  even if cheated.
         if ((newweapon != weapontype_t.wp_plasma
          && newweapon != weapontype_t.wp_bfg)
         || !DS.isShareware() )
         {
         player.pendingweapon = newweapon;
         }
     }
     }
     
     // check for use
     if (flags(cmd.buttons , BT_USE))
     {
     if (!player.usedown)
     {
         P.UseLines (player);
         player.usedown = true;
     }
     }
     else
     player.usedown = false;
     
     // cycle psprites
     player.MovePsprites ();
     
     // Counters, time dependent power ups.

     // Strength counts up to diminish fade.
     if (eval(player.powers[pw_strength]))
     player.powers[pw_strength]++;  
         
     if (eval(player.powers[pw_invulnerability]))
     player.powers[pw_invulnerability]--;

     if (eval(player.powers[pw_invisibility]))
     if (! eval(--player.powers[pw_invisibility]) )
         player.mo.flags &= ~MF_SHADOW;
             
     if (eval(player.powers[pw_infrared]))
     player.powers[pw_infrared]--;
         
     if (eval(player.powers[pw_ironfeet]))
     player.powers[pw_ironfeet]--;
         
     if (eval(player.damagecount))
     player.damagecount--;
         
     if (eval(player.bonuscount))
     player.bonuscount--;

     
     // Handling colormaps.
     if (eval(player.powers[pw_invulnerability]))
     {
     if (player.powers[pw_invulnerability] > 4*32
         || flags(player.powers[pw_invulnerability],8) )
         player.fixedcolormap = player_t.INVERSECOLORMAP;
     else
         player.fixedcolormap = 0;
     }
     else if (eval(player.powers[pw_infrared]))
     {
     if (player.powers[pw_infrared] > 4*32
         || flags(player.powers[pw_infrared],8) )
     {
         // almost full bright
         player.fixedcolormap = 1;
     }
     else
         player.fixedcolormap = 0;
     }
     else
     player.fixedcolormap = 0;
    }

    /**
     * G_PlayerReborn
     * Called after a player dies 
     * almost everything is cleared and initialized 
     *
     *
     */

    public void PlayerReborn () 
    { 
        int     i; 
        int[]     frags=new int [MAXPLAYERS]; 
        int     killcount;
        int     itemcount;
        int     secretcount; 

        // System.arraycopy(players[player].frags, 0, frags, 0, frags.length);
        // We save the player's frags here...
        C2JUtils.memcpy (frags,this.frags,frags.length); 
        killcount = this.killcount; 
        itemcount = this.itemcount; 
        secretcount = this.secretcount; 

        //MAES: we need to simulate an erasure, possibly without making
        // a new object.memset (p, 0, sizeof(*p));
        //players[player]=(player_t) player_t.nullplayer.clone();
        // players[player]=new player_t();
        this.reset();

        // And we copy the old frags into the "new" player. 
        C2JUtils.memcpy(this.frags, frags, this.frags.length); 

        this.killcount = killcount; 
        this.itemcount = itemcount; 
        this.secretcount = secretcount; 

        usedown = attackdown = true;  // don't do anything immediately 
        playerstate = PST_LIVE;       
        health[0] = MAXHEALTH; 
        readyweapon = pendingweapon = weapontype_t.wp_pistol; 
        weaponowned[weapontype_t.wp_fist.ordinal()] = true; 
        weaponowned[weapontype_t.wp_pistol.ordinal()] = true;        
        ammo[ammotype_t.am_clip.ordinal()] = 50; 
        lookdir = 0; // From Heretic

        for (i=0 ; i<NUMAMMO ; i++) 
        	this.maxammo[i] = DoomStatus.maxammo[i]; 

    }

    
    /** Called by Actions ticker */
    public void PlayerThink() {
        PlayerThink(this);       
    }

	@Override
	public void updateStatus(DoomStatus DS) {
	    this.DS=DS;
	    this.DG=DS.DG;
	    this.P=DS.P;
	    this.R=DS.R;
	    this.RND=DS.RND;
	    this.I=DS.I;
	    this.S=DS.S;
	}

	public String toString(){
		sb.setLength(0);
		sb.append("player");
		sb.append(" momx ");
		sb.append(this.mo.momx);
		sb.append(" momy ");
		sb.append(this.mo.momy);
		sb.append(" x ");
		sb.append(this.mo.x);
		sb.append(" y ");
		sb.append(this.mo.y);
		return sb.toString();
	}

	private static StringBuilder sb=new StringBuilder();

    public void read(DataInputStream f) throws IOException{

            // Careful when loading/saving:
            // A player only carries a pointer to a mobj, which is "saved"
            // but later discarded at load time, at least in vanilla. In any case,
           // it has the size of a 32-bit integer, so make sure you skip it.
           // TODO: OK, so vanilla's monsters lost "state" when saved, including non-Doomguy
            //  infighting. Did they "remember" Doomguy too?
            // ANSWER: they didn't.
        
            // The player is special in that it unambigously allows identifying
            // its own map object in an absolute way. Once we identify
            // at least one (e.g. object #45 is pointer 0x43545345) then, since
            // map objects are stored in a nice serialized order.
            this.p_mobj= DoomIO.readLEInt(f); // player mobj pointer
            
            this.playerstate=DoomIO.readLEInt(f);
            this.cmd.read(f);
            this.viewz=DoomIO.readLEInt(f);
            this.viewheight= DoomIO.readLEInt(f);
            this.deltaviewheight= DoomIO.readLEInt(f);
            this.bob=DoomIO.readLEInt(f);
            this.health[0]=DoomIO.readLEInt(f);
            this.armorpoints[0]=DoomIO.readLEInt(f); 
            this.armortype=DoomIO.readLEInt(f); 
            DoomIO.readIntArray(f,this.powers, ByteOrder.LITTLE_ENDIAN); 
            DoomIO.readBooleanIntArray(f,this.cards);
            this.backpack=DoomIO.readIntBoolean(f);
            DoomIO.readIntArray(f,frags, ByteOrder.LITTLE_ENDIAN);
            this.readyweapon=weapontype_t.values()[DoomIO.readLEInt(f)];
            this.pendingweapon=weapontype_t.values()[DoomIO.readLEInt(f)];
            DoomIO.readBooleanIntArray(f,this.weaponowned);
            DoomIO.readIntArray(f,ammo,ByteOrder.LITTLE_ENDIAN);
            DoomIO.readIntArray(f,maxammo,ByteOrder.LITTLE_ENDIAN);
            // Read these as "int booleans"
            this.attackdown=DoomIO.readIntBoolean(f);
            this.usedown=DoomIO.readIntBoolean(f);
            this.cheats=DoomIO.readLEInt(f);
            this.refire=DoomIO.readLEInt(f);
            // For intermission stats.
            this.killcount=DoomIO.readLEInt(f);
            this.itemcount=DoomIO.readLEInt(f);
            this.secretcount=DoomIO.readLEInt(f);
            // Hint messages.
            f.skipBytes(4);
            // For screen flashing (red or bright).
            this.damagecount=DoomIO.readLEInt(f);
            this.bonuscount=DoomIO.readLEInt(f);
            // Who did damage (NULL for floors/ceilings).
            // TODO: must be properly denormalized before saving/loading
            f.skipBytes(4); // TODO: waste a read for attacker mobj.
            // So gun flashes light up areas.
            this.extralight=DoomIO.readLEInt(f);
            // Current PLAYPAL, ???
            //  can be set to REDCOLORMAP for pain, etc.
            this.fixedcolormap=DoomIO.readLEInt(f);
            this.colormap=DoomIO.readLEInt(f);
            // PSPDEF _is_ readable.
            for (pspdef_t p: this.psprites)
                p.read(f);
            this.didsecret=DoomIO.readIntBoolean(f);
            // Total size should be 280 bytes.
        }
    
    public void write(DataOutputStream f) throws IOException{

        // It's much more convenient to pre-buffer, since
        // we'll be writing all Little Endian stuff.
        ByteBuffer b=ByteBuffer.allocate(280);
        this.pack(b);
        // Total size should be 280 bytes.
        // Write everything nicely and at once.        
        f.write(b.array());
    }
    
    // Used to disambiguate between objects
    public int p_mobj;

    @Override
    public void pack(ByteBuffer buf)
            throws IOException {
        
        ByteOrder bo=ByteOrder.LITTLE_ENDIAN;
        buf.order(bo);
        // The player is special in that it unambiguously allows identifying
        // its own map object in an absolute way. Once we identify
        // at least one (e.g. object #45 is pointer 0x43545345) then, since
        // map objects are stored in a nice serialized order by using
        // their next/prev pointers, you can reconstruct their
        // relationships a posteriori.
        // Store our own hashcode or "pointer" if you wish.
        buf.putInt(pointer(mo));
        buf.putInt(playerstate);
        cmd.pack(buf);
        buf.putInt(viewz);        
        buf.putInt(viewheight);
        buf.putInt(deltaviewheight);
        buf.putInt(bob);
        buf.putInt(health[0]);
        buf.putInt(armorpoints[0]); 
        buf.putInt(armortype);
        DoomBuffer.putIntArray(buf,this.powers,this.powers.length,bo); 
        DoomBuffer.putBooleanIntArray(buf,this.cards,this.cards.length, bo);
        DoomBuffer.putBooleanInt(buf,backpack,bo);
        DoomBuffer.putIntArray(buf,this.frags,this.frags.length,bo);
        buf.putInt(readyweapon.ordinal());
        buf.putInt(pendingweapon.ordinal());
        DoomBuffer.putBooleanIntArray(buf,this.weaponowned,this.weaponowned.length, bo);
        DoomBuffer.putIntArray(buf,this.ammo,this.ammo.length, bo);
        DoomBuffer.putIntArray(buf,this.maxammo,this.maxammo.length, bo);
        // Read these as "int booleans"
        DoomBuffer.putBooleanInt(buf,attackdown,bo);
        DoomBuffer.putBooleanInt(buf,usedown,bo);        
        buf.putInt(cheats);
        buf.putInt(refire);
        // For intermission stats.
        buf.putInt(this.killcount);
        buf.putInt(this.itemcount);
        buf.putInt(this.secretcount);
        // Hint messages.
        buf.putInt(0);
        // For screen flashing (red or bright).
        buf.putInt(this.damagecount);
        buf.putInt(this.bonuscount);
        // Who did damage (NULL for floors/ceilings).
        // TODO: must be properly denormalized before saving/loading
        buf.putInt(pointer(attacker));
        // So gun flashes light up areas.
        buf.putInt(this.extralight);
        // Current PLAYPAL, ???
        //  can be set to REDCOLORMAP for pain, etc.
        buf.putInt(this.fixedcolormap);
        buf.putInt(this.colormap);
        // PSPDEF _is_ readable.
        for (pspdef_t p: this.psprites)
            p.pack(buf);
        buf.putInt(this.didsecret?1:0);
        
    }
        
    }
package doom;

/** killough 8/29/98: threads of thinkers, for more efficient searches
 * cph 2002/01/13: for consistency with the main thinker list, keep objects
 * pending deletion on a class list too
 */


public enum th_class {
      th_delete,
      th_misc,
      th_friends,
      th_enemies,
      th_all;
      
      public static final int NUMTHCLASS=th_class.values().length;
}

package doom;

import java.nio.ByteBuffer;

import utils.C2JUtils;
import w.DoomBuffer;

public class doomdata_t implements IDatagramSerializable {

    public static final int DOOMDATALEN=8+data.Defines.BACKUPTICS*ticcmd_t.TICCMDLEN;
    
     // High bit is retransmit request.
     /** MAES: was "unsigned" */
     public int        checksum; 
     
     /* CAREFUL!!! Those "bytes" are actually unsigned
      * 
      */
     
     /** Only valid if NCMD_RETRANSMIT. */     
     public byte        retransmitfrom;
     
     public byte        starttic;
     public byte        player;
     public byte        numtics;
     public ticcmd_t[]        cmds;
     
    public doomdata_t(){
        cmds=new ticcmd_t[data.Defines.BACKUPTICS];
        C2JUtils.initArrayOfObjects(cmds);
        // Enough space for its own header + the ticcmds;
        buffer=new byte[DOOMDATALEN];
        // This "pegs" the ByteBuffer to this particular array.
        // Separate updates are not necessary.
        bbuf=ByteBuffer.wrap(buffer);
    }
    
    // Used for datagram serialization.
    private byte[] buffer;
    private ByteBuffer bbuf;

    
    
    @Override
    public byte[] pack() {        
        
        bbuf.rewind();
        
        // Why making it harder?
        bbuf.putInt(checksum);
        bbuf.put(retransmitfrom);
        bbuf.put(starttic);
        bbuf.put(player);
        bbuf.put(numtics);
        
        // FIXME: it's probably more efficient to use System.arraycopy ? 
        // Or are the packets too small anyway? At most we'll be sending "doomdata_t's"
        
        for (int i=0;i<cmds.length;i++){
            bbuf.put(cmds[i].pack());
        }
        
        return bbuf.array();
    
    }

    @Override
    public void pack(byte[] buf, int offset) {
        
        // No need to make it harder...just pack it and slap it in.
        byte[] tmp=this.pack();
        System.arraycopy(tmp, 0, buf, offset, tmp.length);        
    }

    @Override
    public void unpack(byte[] buf) {
        unpack(buf,0);
    }

    @Override
    public void unpack(byte[] buf, int offset) {
        checksum=DoomBuffer.getBEInt(buf);
        offset=+4;
        retransmitfrom=buf[offset++];
        starttic=buf[offset++];
        player=buf[offset++];
        numtics=buf[offset++];
        
        for (int i=0;i<cmds.length;i++){
            cmds[i].unpack(buf,offset);
            offset+=ticcmd_t.TICCMDLEN;
            }
        
    }
    
    public void selfUnpack(){
        unpack(this.buffer);
    }
    
    public void copyFrom(doomdata_t source) {        
        this.checksum=source.checksum;
        this.numtics=source.numtics;
        this.player=source.player;
        this.retransmitfrom=source.retransmitfrom;
        this.starttic=source.starttic;
        
        // MAES: this was buggy as hell, and didn't work at all, which
        // in turn prevented other subsystems such as speed throttling and
        // networking to work.
        // 
        // This should be enough to alter the ByteBuffer too.
        //System.arraycopy(source.cached(), 0, this.buffer, 0, DOOMDATALEN);
        // This should set all fields
        //selfUnpack();        
        }
    
    @Override
     public byte[] cached(){
         return this.buffer;
     }
    
    StringBuilder sb=new StringBuilder();
    public String toString(){
        sb.setLength(0);
        sb.append("doomdata_t ");
        sb.append(retransmitfrom);
        sb.append(" starttic ");
        sb.append(starttic);
        sb.append(" player ");
        sb.append(player);
        sb.append(" numtics ");
        sb.append(numtics);
        return sb.toString();
        
    }

 }

package doom;
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: net.java,v 1.5 2011/02/11 00:11:13 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: net.java,v $
// Revision 1.5  2011/02/11 00:11:13  velktron
// A MUCH needed update to v1.3.
//
// Revision 1.1  2010/06/30 08:58:50  velktron
// Let's see if this stuff will finally commit....
//
//
// Most stuff is still  being worked on. For a good place to start and get an idea of what is being done, I suggest checking out the "testers" package.
//
// Revision 1.1  2010/06/29 11:07:34  velktron
// Release often, release early they say...
//
// Commiting ALL stuff done so far. A lot of stuff is still broken/incomplete, and there's still mixed C code in there. I suggest you load everything up in Eclpise and see what gives from there.
//
// A good place to start is the testers/ directory, where you  can get an idea of how a few of the implemented stuff works.
//
//
// DESCRIPTION:
//	DOOM Network game communication and protocol,
//	all OS independend parts.
//
//-----------------------------------------------------------------------------


//static const char rcsid[] = "$Id: net.java,v 1.5 2011/02/11 00:11:13 velktron Exp $";


//#include "m_menu.h"
//#include "i_system.h"
//#include "i_video.h"
//#include "i_net.h"
//#include "g_game.h"
import static data.Defines.*;
import data.doomstat.*;

//
//Network play related stuff.
//There is a data struct that stores network
//communication related stuff, and another
//one that defines the actual packets to
//be transmitted.
//


public class net{

protected static int	NCMD_EXIT=		0x80000000;
protected static int   	NCMD_RETRANSMIT		=0x40000000;
protected static int   	NCMD_SETUP		=0x20000000;
protected static int   NCMD_KILL	=	0x10000000;	// kill game
protected static int   	NCMD_CHECKSUM	= 	0x0fffffff;

protected static int  DOOMCOM_ID =     0x12345678;

//Max computers/players in a game.
protected static int    MAXNETNODES   =  8;


//Networking and tick handling related.
protected static int    BACKUPTICS     = 12;


// commant_t
protected  static int CMD_SEND    = 1;
protected  static int CMD_GET = 2; 

doomcom_t	doomcom;	
doomdata_t	netbuffer;		// points inside doomcom


//
// NETWORKING
//
// gametic is the tic about to (or currently being) run
// maketic is the tick that hasn't had control made for it yet
// nettics[] has the maketics for all players 
//
// a gametic cannot be run until nettics[] > gametic for all players
//
public static int	RESENDCOUNT	=10;
public static int	PL_DRONE	=0x80;	// bit flag in doomdata->player

ticcmd_t[]	localcmds= new ticcmd_t[BACKUPTICS];

ticcmd_t [][]       netcmds=new ticcmd_t [MAXPLAYERS][BACKUPTICS];
int[]         	nettics=new int[MAXNETNODES];
boolean[]		nodeingame=new boolean[MAXNETNODES];		// set false as nodes leave game
boolean[]		remoteresend=new boolean[MAXNETNODES];		// set when local needs tics
int[]		resendto=new int[MAXNETNODES];			// set when remote needs tics
int[]		resendcount=new int[MAXNETNODES];

int[]		nodeforplayer=new int[MAXPLAYERS];

int             maketic;
int		lastnettic;
int		skiptics;
int		ticdup;		
int		maxsend;	// BACKUPTICS/(2*ticdup)-1


//void D_ProcessEvents (void); 
//void G_BuildTiccmd (ticcmd_t *cmd); 
//void D_DoAdvanceDemo (void);
 
boolean		reboundpacket;
doomdata_t	reboundstore;



// 
//
//123

/** MAES: interesting. After testing it was found to return the following size:
 * 
 */

int NetbufferSize ()
{
//    return (int)(((doomdata_t)0).cmds[netbuffer.numtics]);
    return (8*(netbuffer.numtics+1));
}

}
/*

//1
// Checksum 
//
unsigned NetbufferChecksum (void)
{
    unsigned		c;
    int		i,l;

    c = 0x1234567;

    // FIXME -endianess?
#ifdef NORMALUNIX
    return 0;			// byte order problems
#endif

    l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
    for (i=0 ; i<l ; i++)
	c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);

    return c & NCMD_CHECKSUM;
}

//
//
//
int ExpandTics (int low)
{
    int	delta;
	
    delta = low - (maketic&0xff);
	
    if (delta >= -64 && delta <= 64)
	return (maketic&~0xff) + low;
    if (delta > 64)
	return (maketic&~0xff) - 256 + low;
    if (delta < -64)
	return (maketic&~0xff) + 256 + low;
		
    I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic);
    return 0;
}



//
// HSendPacket
//
void
HSendPacket
 (int	node,
  int	flags )
{
    netbuffer->checksum = NetbufferChecksum () | flags;

    if (!node)
    {
	reboundstore = *netbuffer;
	reboundpacket = true;
	return;
    }

    if (demoplayback)
	return;

    if (!netgame)
	I_Error ("Tried to transmit to another node");
		
    doomcom->command = CMD_SEND;
    doomcom->remotenode = node;
    doomcom->datalength = NetbufferSize ();
	
    if (debugfile)
    {
	int		i;
	int		realretrans;
	if (netbuffer->checksum & NCMD_RETRANSMIT)
	    realretrans = ExpandTics (netbuffer->retransmitfrom);
	else
	    realretrans = -1;

	fprintf (debugfile,"send (%i + %i, R %i) [%i] ",
		 ExpandTics(netbuffer->starttic),
		 netbuffer->numtics, realretrans, doomcom->datalength);
	
	for (i=0 ; i<doomcom->datalength ; i++)
	    fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);

	fprintf (debugfile,"\n");
    }

    I_NetCmd ();
}

//
// HGetPacket
// Returns false if no packet is waiting
//
boolean HGetPacket (void)
{	
    if (reboundpacket)
    {
	*netbuffer = reboundstore;
	doomcom->remotenode = 0;
	reboundpacket = false;
	return true;
    }

    if (!netgame)
	return false;

    if (demoplayback)
	return false;
		
    doomcom->command = CMD_GET;
    I_NetCmd ();
    
    if (doomcom->remotenode == -1)
	return false;

    if (doomcom->datalength != NetbufferSize ())
    {
	if (debugfile)
	    fprintf (debugfile,"bad packet length %i\n",doomcom->datalength);
	return false;
    }
	
    if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) )
    {
	if (debugfile)
	    fprintf (debugfile,"bad packet checksum\n");
	return false;
    }

    if (debugfile)
    {
	int		realretrans;
	int	i;
			
	if (netbuffer->checksum & NCMD_SETUP)
	    fprintf (debugfile,"setup packet\n");
	else
	{
	    if (netbuffer->checksum & NCMD_RETRANSMIT)
		realretrans = ExpandTics (netbuffer->retransmitfrom);
	    else
		realretrans = -1;
	    
	    fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",
		     doomcom->remotenode,
		     ExpandTics(netbuffer->starttic),
		     netbuffer->numtics, realretrans, doomcom->datalength);

	    for (i=0 ; i<doomcom->datalength ; i++)
		fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
	    fprintf (debugfile,"\n");
	}
    }
    return true;	
}


//
// GetPackets
//
char    exitmsg[80];

void GetPackets (void)
{
    int		netconsole;
    int		netnode;
    ticcmd_t	*src, *dest;
    int		realend;
    int		realstart;
				 
    while ( HGetPacket() )
    {
	if (netbuffer->checksum & NCMD_SETUP)
	    continue;		// extra setup packet
			
	netconsole = netbuffer->player & ~PL_DRONE;
	netnode = doomcom->remotenode;
	
	// to save bytes, only the low byte of tic numbers are sent
	// Figure out what the rest of the bytes are
	realstart = ExpandTics (netbuffer->starttic);		
	realend = (realstart+netbuffer->numtics);
	
	// check for exiting the game
	if (netbuffer->checksum & NCMD_EXIT)
	{
	    if (!nodeingame[netnode])
		continue;
	    nodeingame[netnode] = false;
	    playeringame[netconsole] = false;
	    strcpy (exitmsg, "Player 1 left the game");
	    exitmsg[7] += netconsole;
	    players[consoleplayer].message = exitmsg;
	    if (demorecording)
		G_CheckDemoStatus ();
	    continue;
	}
	
	// check for a remote game kill
	if (netbuffer->checksum & NCMD_KILL)
	    I_Error ("Killed by network driver");

	nodeforplayer[netconsole] = netnode;
	
	// check for retransmit request
	if ( resendcount[netnode] <= 0 
	     && (netbuffer->checksum & NCMD_RETRANSMIT) )
	{
	    resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
	    if (debugfile)
		fprintf (debugfile,"retransmit from %i\n", resendto[netnode]);
	    resendcount[netnode] = RESENDCOUNT;
	}
	else
	    resendcount[netnode]--;
	
	// check for out of order / duplicated packet		
	if (realend == nettics[netnode])
	    continue;
			
	if (realend < nettics[netnode])
	{
	    if (debugfile)
		fprintf (debugfile,
			 "out of order packet (%i + %i)\n" ,
			 realstart,netbuffer->numtics);
	    continue;
	}
	
	// check for a missed packet
	if (realstart > nettics[netnode])
	{
	    // stop processing until the other system resends the missed tics
	    if (debugfile)
		fprintf (debugfile,
			 "missed tics from %i (%i - %i)\n",
			 netnode, realstart, nettics[netnode]);
	    remoteresend[netnode] = true;
	    continue;
	}

	// update command store from the packet
        {
	    int		start;

	    remoteresend[netnode] = false;
		
	    start = nettics[netnode] - realstart;		
	    src = &netbuffer->cmds[start];

	    while (nettics[netnode] < realend)
	    {
		dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS];
		nettics[netnode]++;
		*dest = *src;
		src++;
	    }
	}
    }
}


//
// NetUpdate
// Builds ticcmds for console player,
// sends out a packet
//
int      gametime;

void NetUpdate (void)
{
    int             nowtime;
    int             newtics;
    int				i,j;
    int				realstart;
    int				gameticdiv;
    
    // check time
    nowtime = I_GetTime ()/ticdup;
    newtics = nowtime - gametime;
    gametime = nowtime;
	
    if (newtics <= 0) 	// nothing new to update
	goto listen; 

    if (skiptics <= newtics)
    {
	newtics -= skiptics;
	skiptics = 0;
    }
    else
    {
	skiptics -= newtics;
	newtics = 0;
    }
	
		
    netbuffer->player = consoleplayer;
    
    // build new ticcmds for console player
    gameticdiv = gametic/ticdup;
    for (i=0 ; i<newtics ; i++)
    {
	I_StartTic ();
	D_ProcessEvents ();
	if (maketic - gameticdiv >= BACKUPTICS/2-1)
	    break;          // can't hold any more
	
	//printf ("mk:%i ",maketic);
	G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]);
	maketic++;
    }


    if (singletics)
	return;         // singletic update is syncronous
    
    // send the packet to the other nodes
    for (i=0 ; i<doomcom->numnodes ; i++)
	if (nodeingame[i])
	{
	    netbuffer->starttic = realstart = resendto[i];
	    netbuffer->numtics = maketic - realstart;
	    if (netbuffer->numtics > BACKUPTICS)
		I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS");

	    resendto[i] = maketic - doomcom->extratics;

	    for (j=0 ; j< netbuffer->numtics ; j++)
		netbuffer->cmds[j] = 
		    localcmds[(realstart+j)%BACKUPTICS];
					
	    if (remoteresend[i])
	    {
		netbuffer->retransmitfrom = nettics[i];
		HSendPacket (i, NCMD_RETRANSMIT);
	    }
	    else
	    {
		netbuffer->retransmitfrom = 0;
		HSendPacket (i, 0);
	    }
	}
    
    // listen for other packets
  listen:
    GetPackets ();
}



//
// CheckAbort
//
void CheckAbort (void)
{
    event_t *ev;
    int		stoptic;
	
    stoptic = I_GetTime () + 2; 
    while (I_GetTime() < stoptic) 
	I_StartTic (); 
	
    I_StartTic ();
    for ( ; eventtail != eventhead 
	      ; eventtail = (++eventtail)&(MAXEVENTS-1) ) 
    { 
	ev = &events[eventtail]; 
	if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
	    I_Error ("Network game synchronization aborted.");
    } 
}


//
// D_ArbitrateNetStart
//
void D_ArbitrateNetStart (void)
{
    int		i;
    boolean	gotinfo[MAXNETNODES];
	
    autostart = true;
    memset (gotinfo,0,sizeof(gotinfo));
	
    if (doomcom->consoleplayer)
    {
	// listen for setup info from key player
	printf ("listening for network start info...\n");
	while (1)
	{
	    CheckAbort ();
	    if (!HGetPacket ())
		continue;
	    if (netbuffer->checksum & NCMD_SETUP)
	    {
		if (netbuffer->player != VERSION)
		    I_Error ("Different DOOM versions cannot play a net game!");
		startskill = netbuffer->retransmitfrom & 15;
		deathmatch = (netbuffer->retransmitfrom & 0xc0) >> 6;
		nomonsters = (netbuffer->retransmitfrom & 0x20) > 0;
		respawnparm = (netbuffer->retransmitfrom & 0x10) > 0;
		startmap = netbuffer->starttic & 0x3f;
		startepisode = netbuffer->starttic >> 6;
		return;
	    }
	}
    }
    else
    {
	// key player, send the setup info
	printf ("sending network start info...\n");
	do
	{
	    CheckAbort ();
	    for (i=0 ; i<doomcom->numnodes ; i++)
	    {
		netbuffer->retransmitfrom = startskill;
		if (deathmatch)
		    netbuffer->retransmitfrom |= (deathmatch<<6);
		if (nomonsters)
		    netbuffer->retransmitfrom |= 0x20;
		if (respawnparm)
		    netbuffer->retransmitfrom |= 0x10;
		netbuffer->starttic = startepisode * 64 + startmap;
		netbuffer->player = VERSION;
		netbuffer->numtics = 0;
		HSendPacket (i, NCMD_SETUP);
	    }

#if 1
	    for(i = 10 ; i  &&  HGetPacket(); --i)
	    {
		if((netbuffer->player&0x7f) < MAXNETNODES)
		    gotinfo[netbuffer->player&0x7f] = true;
	    }
#else
	    while (HGetPacket ())
	    {
		gotinfo[netbuffer->player&0x7f] = true;
	    }
#endif

	    for (i=1 ; i<doomcom->numnodes ; i++)
		if (!gotinfo[i])
		    break;
	} while (i < doomcom->numnodes);
    }
}

//
// D_CheckNetGame
// Works out player numbers among the net participants
//
extern	int			viewangleoffset;

void D_CheckNetGame (void)
{
    int             i;
	
    for (i=0 ; i<MAXNETNODES ; i++)
    {
	nodeingame[i] = false;
       	nettics[i] = 0;
	remoteresend[i] = false;	// set when local needs tics
	resendto[i] = 0;		// which tic to start sending
    }
	
    // I_InitNetwork sets doomcom and netgame
    I_InitNetwork ();
    if (doomcom->id != DOOMCOM_ID)
	I_Error ("Doomcom buffer invalid!");
    
    netbuffer = &doomcom->data;
    consoleplayer = displayplayer = doomcom->consoleplayer;
    if (netgame)
	D_ArbitrateNetStart ();

    printf ("startskill %i  deathmatch: %i  startmap: %i  startepisode: %i\n",
	    startskill, deathmatch, startmap, startepisode);
	
    // read values out of doomcom
    ticdup = doomcom->ticdup;
    maxsend = BACKUPTICS/(2*ticdup)-1;
    if (maxsend<1)
	maxsend = 1;
			
    for (i=0 ; i<doomcom->numplayers ; i++)
	playeringame[i] = true;
    for (i=0 ; i<doomcom->numnodes ; i++)
	nodeingame[i] = true;
	
    printf ("player %i of %i (%i nodes)\n",
	    consoleplayer+1, doomcom->numplayers, doomcom->numnodes);

}


//
// D_QuitNetGame
// Called before quitting to leave a net game
// without hanging the other players
//
void D_QuitNetGame (void)
{
    int             i, j;
	
    if (debugfile)
	fclose (debugfile);
		
    if (!netgame || !usergame || consoleplayer == -1 || demoplayback)
	return;
	
    // send a bunch of packets for security
    netbuffer->player = consoleplayer;
    netbuffer->numtics = 0;
    for (i=0 ; i<4 ; i++)
    {
	for (j=1 ; j<doomcom->numnodes ; j++)
	    if (nodeingame[j])
		HSendPacket (j, NCMD_EXIT);
	I_WaitVBL (1);
    }
}



//
// TryRunTics
//
int	frametics[4];
int	frameon;
int	frameskip[4];
int	oldnettics;

extern	boolean	advancedemo;

public static void TryRunTics ()
{
    int		i;
    int		lowtic;
    int		entertic;
    static int	oldentertics;
    int		realtics;
    int		availabletics;
    int		counts;
    int		numplaying;
    
    // get real tics		
    entertic = I_GetTime ()/ticdup;
    realtics = entertic - oldentertics;
    oldentertics = entertic;
    
    // get available tics
    NetUpdate ();
	
    lowtic = MAXINT;
    numplaying = 0;
    for (i=0 ; i<doomcom->numnodes ; i++)
    {
	if (nodeingame[i])
	{
	    numplaying++;
	    if (nettics[i] < lowtic)
		lowtic = nettics[i];
	}
    }
    availabletics = lowtic - gametic/ticdup;
    
    // decide how many tics to run
    if (realtics < availabletics-1)
	counts = realtics+1;
    else if (realtics < availabletics)
	counts = realtics;
    else
	counts = availabletics;
    
    if (counts < 1)
	counts = 1;
		
    frameon++;

    if (debugfile)
	fprintf (debugfile,
		 "=======real: %i  avail: %i  game: %i\n",
		 realtics, availabletics,counts);

    if (!demoplayback)
    {	
	// ideally nettics[0] should be 1 - 3 tics above lowtic
	// if we are consistantly slower, speed up time
	for (i=0 ; i<MAXPLAYERS ; i++)
	    if (playeringame[i])
		break;
	if (consoleplayer == i)
	{
	    // the key player does not adapt
	}
	else
	{
	    if (nettics[0] <= nettics[nodeforplayer[i]])
	    {
		gametime--;
		// printf ("-");
	    }
	    frameskip[frameon&3] = (oldnettics > nettics[nodeforplayer[i]]);
	    oldnettics = nettics[0];
	    if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
	    {
		skiptics = 1;
		// printf ("+");
	    }
	}
    }// demoplayback
	
    // wait for new tics if needed
    while (lowtic < gametic/ticdup + counts)	
    {
	NetUpdate ();   
	lowtic = MAXINT;
	
	for (i=0 ; i<doomcom->numnodes ; i++)
	    if (nodeingame[i] && nettics[i] < lowtic)
		lowtic = nettics[i];
	
	if (lowtic < gametic/ticdup)
	    I_Error ("TryRunTics: lowtic < gametic");
				
	// don't stay in here forever -- give the menu a chance to work
	if (I_GetTime ()/ticdup - entertic >= 20)
	{
	    M_Ticker ();
	    return;
	} 
    }
    
    // run the count * ticdup dics
    while (counts--)
    {
	for (i=0 ; i<ticdup ; i++)
	{
	    if (gametic/ticdup > lowtic)
		I_Error ("gametic>lowtic");
	    if (advancedemo)
		D_DoAdvanceDemo ();
	    M_Ticker ();
	    G_Ticker ();
	    gametic++;
	    
	    // modify command for duplicated tics
	    if (i != ticdup-1)
	    {
		ticcmd_t	*cmd;
		int			buf;
		int			j;
				
		buf = (gametic/ticdup)%BACKUPTICS; 
		for (j=0 ; j<MAXPLAYERS ; j++)
		{
		    cmd = &netcmds[j][buf];
		    cmd->chatchar = 0;
		    if (cmd->buttons & BT_SPECIAL)
			cmd->buttons = 0;
		}
	    }
	}
	NetUpdate ();	// check for new console commands
    }
}
}*/
package doom;

public class doomcom_t {
	
		public doomcom_t(){
			this.data=new doomdata_t();
			
		}

        // Supposed to be DOOMCOM_ID?
        // Maes: was "long", but they intend 32-bit "int" here. Hurray for C's consistency!
        public int        id;
        
        // DOOM executes an int to execute commands.
        public short       intnum;     
        // Communication between DOOM and the driver.
        // Is CMD_SEND or CMD_GET.
        public short       command;
        // Is dest for send, set by get (-1 = no packet).
        public short       remotenode;
        
        // Number of bytes in doomdata to be sent
        public short       datalength;

        // Info common to all nodes.
        // Console is allways node 0.
        public short       numnodes;
        // Flag: 1 = no duplication, 2-5 = dup for slow nets.
        public short       ticdup;
        // Flag: 1 = send a backup tic in every packet.
        public short       extratics;
        // Flag: 1 = deathmatch.
        public short       deathmatch;
        // Flag: -1 = new game, 0-5 = load savegame
        public short       savegame;
        public short       episode;    // 1-3
        public short       map;        // 1-9
        public short       skill;      // 1-5

        // Info specific to this node.
        public short       consoleplayer;
        public short       numplayers;
        
        // These are related to the 3-display mode,
        //  in which two drones looking left and right
        //  were used to render two additional views
        //  on two additional computers.
        // Probably not operational anymore.
        // 1 = left, 0 = center, -1 = right
        public short       angleoffset;
        // 1 = drone
        public short       drone;      

        // The packet data to be sent.
        public doomdata_t      data;
        
    }

package doom;

public class pic_t {
    
    public pic_t(byte width, byte height, byte data) {
        super();
        this.width = width;
        this.height = height;
        this.data = data;
    }
    
    public byte        width;
    public byte        height;
    public byte        data;
}


package doom;

/** The defined weapons,
 * including a marker indicating
 *  user has not changed weapon.
 */
public enum weapontype_t
{
    wp_fist,
    wp_pistol,
    wp_shotgun,
    wp_chaingun,
    wp_missile,
    wp_plasma,
    wp_bfg,
    wp_chainsaw,
    wp_supershotgun,

    NUMWEAPONS,
    
    // No pending weapon change.
    wp_nochange;
    
    public String toString(){
        return this.name();
    }
    
}

package doom;

import static utils.C2JUtils.eval;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;

import w.DoomIO;

/**
 * A class to handle the command-line args in an unified manner, and without
 * them being tied to DoomMain or DoomStatus.
 * 
 * 
 * @author velktron
 *
 */

public class CommandLine implements ICommandLineManager {

    
    /* What bullshit, those are supposed to carry over from the very first main */
    protected int myargc;
    protected String[] myargv;
    
    public CommandLine(String[] argv){

        // Bump argcount up by 1 to maintain CheckParm behavior
        // In C, argument 0 is the executable itself, and most
        // of Doom's code is tailored to reflect that, with 0
        // meaning "not found" with regards to a parameter.
        // It's easier to change this here.
    	// TODO: this is really bad practice, eliminate once a 
    	// cvar system is in place.

        myargv=new String[argv.length+1];
        System.arraycopy(argv, 0, myargv, 1, argv.length);        
        myargc=argv.length+1;
        cvars=new HashMap<String, Object>();
    }
    
    /* (non-Javadoc)
     * @see doom.ICommandLineManager#getArgv(int)
     */
    @Override
    public String getArgv(int index){
        if (index>myargc) return null;
        else return myargv[index];
    }
    
    /* (non-Javadoc)
     * @see doom.ICommandLineManager#getArgc()
     */
    @Override
    public int getArgc(){
        return myargc;
    }
    

    /* (non-Javadoc)
     * @see doom.ICommandLineManager#CheckParm(java.lang.String)
     */

    @Override
    public int CheckParm(String check) {
        int i;

        for (i = 1; i < myargc; i++) {
            if (check.compareToIgnoreCase(myargv[i]) == 0)
                return i;
        }

        return 0;
    }
    
    @Override
    public boolean CheckParmBool(String check) {
        int i;

        for (i = 1; i < myargc; i++) {
            if (check.compareToIgnoreCase(myargv[i]) == 0)
                return true;
        }

        return false;
    }
    
    /**
     * Find a Response File
     * 
     * Not very well documented, but Doom apparently could use a sort of 
     * script file with command line arguments inside, if you prepend @ to
     * the command-like argument itself. The arguments themselves could
     * be separated by any sort of whitespace or ASCII characters exceeding "z"
     * in value.
     * 
     * E.g. doom @crap
     * 
     * would load a file named "crap".
     * 
     * Now, the original function is crap for several reasons: for one,
     * it will bomb if more than 100 arguments <i>total</i> are formed.
     * Memory allocation will also fail because the tokenizer used only
     * stops at file size limit, not at maximum parsed arguments limit
     * (MACARGVS = 100).
     * 
     * This is the wiki's entry:
     * 
     * doom @<response>
     * This parameter tells the Doom engine to read from a response file, 
     * a text file that may store additional command line parameters. 
     * The file may have any name that is valid to the system, optionally 
     * with an extension. The parameters are typed as in the command line 
     * (-episode 2, for example), but one per line, where up to 100 lines
     *  may be used. The additional parameters may be disabled for later 
     *  use by placing a vertical bar (the | character) between the 
     *  prefixing dash (-) and the rest of the parameter name.
     * 
     * 
     */
    @Override
    public void FindResponseFile ()
    {
        try{

            for (int i = 1;i < getArgc();i++)
                if (getArgv(i).charAt(0)=='@')
                {
                    DataInputStream handle;
                    // save o       
                    int             size;
                    int             indexinfile;
                    char[]   infile=null;
                    char[]    file=null;
                    // Fuck that, we're doing it properly.
                    ArrayList<String>  parsedargs=new ArrayList<String>();
                    ArrayList<String>    moreargs=new ArrayList<String>();
                    String    firstargv;

                    // READ THE RESPONSE FILE INTO MEMORY
                    handle = new DataInputStream(new BufferedInputStream(new FileInputStream(myargv[i].substring(1))));
                    if (!eval(handle))
                    {
                        System.out.print ("\nNo such response file!");
                        System.exit(1);
                    }
                    System.out.println("Found response file "+myargv[i].substring(1));
                    size = (int) handle.available();
                    file=new char[size];
                    
                    DoomIO.readNonUnicodeCharArray(handle, file,size);
                    handle.close();

                    // Save first argument.
                    firstargv = myargv[0];

                    // KEEP ALL CMDLINE ARGS FOLLOWING @RESPONSEFILE ARG
                    // This saves the old references.
                    for (int k = i+1; k < myargc; k++)
                        moreargs.add(myargv[k]);

                    infile = file;
                    indexinfile = 0;
                    indexinfile++;  // SKIP PAST ARGV[0] (KEEP IT)
                    // HMM? StringBuffer build=new StringBuffer();

                    /* MAES: the code here looked like some primitive tokenizer.
           that assigned C-strings to memory locations.
           Instead, we'll tokenize the file input correctly here.
                     */

                    StringTokenizer tk=new StringTokenizer(String.copyValueOf(infile));



                    //myargv = new String[tk.countTokens()+argc];
                    parsedargs.add(firstargv);

                    while(tk.hasMoreTokens())
                    {
                        parsedargs.add(tk.nextToken());
                    }

                    // Append the other args to the end.
                    parsedargs.addAll(moreargs);

                    /* NOW the original myargv is reset, but the old values still survive in 
                     * the listarray.*/

                    myargv= new String[parsedargs.size()];
                    myargv=parsedargs.toArray(myargv);
                    myargc = myargv.length;

                    // DISPLAY ARGS
                    System.out.println(myargc+" command-line args:");
                    for (int k=0;k<myargc;k++)
                        System.out.println(myargv[k]);

                    // Stops at the first one. Pity, because we could do funky recursive stuff with that :-p
                    break;
                }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void setArgv(int index, String string) {
        this.myargv[index]=string;
        
    }
    
    private HashMap<String, Object> cvars;
    
    public boolean cvarExists(String name){
    	return cvars.containsKey(name);
    	}
    
    public Object removeCvar(String name){
    	return cvars.remove(name);
    	}
    
    public void putCvar(String name, int value){
    	cvars.put(name, value);
    	}

    public void putCvar(String name, double value){
    	cvars.put(name, value);
    	}
    
    public void putCvar(String name, String value){
    	cvars.put(name, value);
    	}

    public void putCvar(String name, boolean value){
    	cvars.put(name, value);
    	}

    public void putCvar(String name, String[] value){
    	cvars.put(name, value);
    	}
    
    public Integer getInt(String name){
    	Object stuff=cvars.get(name);
    	if (stuff !=null){
    		if (stuff instanceof Integer){
    			return (Integer) stuff;
    		}
    	}    	
    	return null;
    }
    
    public Double getFloat(String name){
    	Object stuff=cvars.get(name);
    	if (stuff !=null){
    		if (stuff instanceof Double){
    			return (Double) stuff;
    		}
    	}    	
    	return null;
    }
    
    public String getString(String name){
    	Object stuff=cvars.get(name);
    	if (stuff !=null){
    		if (stuff instanceof String){
    			return (String) stuff;
    		}
    	}    	
    	return null;
    }
    
    public String[] getStringArray(String name){
    	Object stuff=cvars.get(name);
    	if (stuff !=null){
    		if (stuff instanceof String[]){
    			return (String[]) stuff;
    		}
    	}    	
    	return null;
    }
    
    public Boolean getBoolean(String name){
    	Object stuff=cvars.get(name);
    	if (stuff !=null){
    		if (stuff instanceof Boolean){
    			return (Boolean) stuff;
    		}
    	}    	
    	return null;
    }
    
    public <K> void setCvar(String name, K value){
    	if (cvars.containsKey(name)){
    		cvars.put(name, value);
    	}
    }

    public static String checkParameterCouple(String check, String[] myargv) {
        int found=-1;

        for (int i = 0; i < myargv.length; i++) {
            if (check.compareToIgnoreCase(myargv[i]) == 0){
                found=i; // found. Break on first.
                break;
            }
        }
        
        // Found, and there's room to spare for one more?
        if ((found>=0)&&(found<myargv.length-1)){
            if (myargv[found+1]!=null){
                // Not null, not empty and not a parameter switch
                if ((myargv[found+1].length()>=1) &&
                    (myargv[found+1].charAt(0)!='-'))                        
                        return myargv[found+1];
            }
        }

        // Well duh.
        return null;
    }
 
    /** Is a parameter based on an prefix identifier e.g. '-'
     * 
     * @param what
     * @param identifier
     * @return
     */
    public static boolean isParameter(String what, char identifier){
        if (what!=null && what.length()>-0){
        	return (what.charAt(0)!=identifier); 
        }
        
        return false;        
    }
    
    public static int parameterMultipleValues(String check, String[] myargv) {
        int found=-1;

        // It's not even a valid parameter name
        if (!isParameter(check,'-')) return -1;
        
        // Does it exist?
        if ((found=checkParm(check,myargv))==-1) return found;
        
        // Found, and there are still some to spare
        int rest=myargv.length-found-1;
        int count=0;
        
        for (int i=found+1;i<myargv.length;i++){
        	if (isParameter(myargv[i],'-')) break;
        		else
        	count++; // not a parameter, count up        	
        }
        
        // Well duh.
        return count;
    }
    
    
    public static int checkParm(String check, String[] params) {
        int i;

        for (i = 0; i < params.length; i++) {
            if (check.compareToIgnoreCase(params[i]) == 0)
                return i;
        }

        return -1;
    }
    
}

package doom;

import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import static utils.C2JUtils.pointer;
import w.CacheableDoomObject;
import w.IPackableDoomObject;
import w.IReadableDoomObject;
import p.ActionType1;
import p.ActionType2;
import p.ActionTypeSS;

public class thinker_t implements CacheableDoomObject,IReadableDoomObject,IPackableDoomObject{
   
   public thinker_t prev;
   public thinker_t next;
   public think_t     function;

   /* killough 8/29/98: we maintain thinkers in several equivalence classes,
    * according to various criteria, so as to allow quicker searches.
    */

   /** Next, previous thinkers in same class */
   
   public thinker_t cnext, cprev;

   
   // Thinkers can either have one parameter of type (mobj_t),
   // Or otherwise be sector specials, flickering lights etc.
   // Those are atypical and need special handling.
   public ActionType1     acp1;
   public ActionType2     acp2;
   public ActionTypeSS     acpss;
   
   /** extra fields, to use when archiving/unarchiving for
    * identification. Also in blocklinks, etc.
    */
   public int id,previd, nextid,functionid;
   
   
   
@Override
public void read(DataInputStream f)
        throws IOException {
	readbuffer.position(0);
	readbuffer.order(ByteOrder.LITTLE_ENDIAN);
	f.read(readbuffer.array());
	unpack(readbuffer);
	}

/** This adds 12 bytes */

@Override
public void pack(ByteBuffer b)
        throws IOException {
    // It's possible to reconstruct even by hashcodes.
    // As for the function, that should be implied by the mobj_t type.
	b.order(ByteOrder.LITTLE_ENDIAN);
	b.putInt(pointer(prev));
    b.putInt(pointer(next));
    b.putInt(pointer(function));
    //System.out.printf("Packed thinker %d %d %d\n",pointer(prev),pointer(next),pointer(function));
	}

@Override
public void unpack(ByteBuffer b)
        throws IOException {
    // We are supposed to archive pointers to other thinkers,
    // but they are rather useless once on disk.
	b.order(ByteOrder.LITTLE_ENDIAN);
    previd=b.getInt();
    nextid=b.getInt();
    functionid=b.getInt();
    //System.out.printf("Unpacked thinker %d %d %d\n",pointer(previd),pointer(nextid),pointer(functionid));
	}

 private static ByteBuffer readbuffer=ByteBuffer.allocate(12);

}
package doom;
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: items.java,v 1.3 2010/12/20 17:15:08 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: items.java,v $
// Revision 1.3  2010/12/20 17:15:08  velktron
// Made the renderer more OO -> TextureManager and other changes as well.
//
// Revision 1.2  2010/08/19 23:14:49  velktron
// Automap
//
// Revision 1.1  2010/06/30 08:58:50  velktron
// Let's see if this stuff will finally commit....
//
//
// Most stuff is still  being worked on. For a good place to start and get an idea of what is being done, I suggest checking out the "testers" package.
//
// Revision 1.1  2010/06/29 11:07:34  velktron
// Release often, release early they say...
//
// Commiting ALL stuff done so far. A lot of stuff is still broken/incomplete, and there's still mixed C code in there. I suggest you load everything up in Eclpise and see what gives from there.
//
// A good place to start is the testers/ directory, where you  can get an idea of how a few of the implemented stuff works.
//
//
// DESCRIPTION:
//
//-----------------------------------------------------------------------------

import defines.*;

public class items{

public static weaponinfo_t[]	weaponinfo=
{
    new weaponinfo_t(
	// fist
	ammotype_t.am_noammo,
	statenum_t.S_PUNCHUP,
	statenum_t.S_PUNCHDOWN,
	statenum_t.S_PUNCH,
	statenum_t.S_PUNCH1,
	statenum_t.S_NULL
    ),	
    new weaponinfo_t(
	// pistol
    ammotype_t.am_clip,
	statenum_t.S_PISTOLUP,
	statenum_t.S_PISTOLDOWN,
	statenum_t.S_PISTOL,
	statenum_t.S_PISTOL1,
	statenum_t.S_PISTOLFLASH
	), new weaponinfo_t(
	// shotgun
    ammotype_t.am_shell,
    statenum_t.S_SGUNUP,
    statenum_t.S_SGUNDOWN,
    statenum_t.S_SGUN,
    statenum_t.S_SGUN1,
    statenum_t.S_SGUNFLASH1
    ),
    new weaponinfo_t(
	// chaingun
    ammotype_t.am_clip,
	statenum_t.S_CHAINUP,
	statenum_t.S_CHAINDOWN,
	statenum_t.S_CHAIN,
	statenum_t.S_CHAIN1,
	statenum_t.S_CHAINFLASH1
    ),
    new weaponinfo_t(
	// missile launcher
        ammotype_t.am_misl,
	statenum_t.S_MISSILEUP,
	statenum_t.S_MISSILEDOWN,
	statenum_t.S_MISSILE,
	statenum_t.S_MISSILE1,
	statenum_t.S_MISSILEFLASH1
    ),
    new weaponinfo_t(
	// plasma rifle
        ammotype_t.am_cell,
	statenum_t.S_PLASMAUP,
	statenum_t.S_PLASMADOWN,
	statenum_t.S_PLASMA,
	statenum_t.S_PLASMA1,
	statenum_t.S_PLASMAFLASH1
    ),
    new weaponinfo_t(
	// bfg 9000
        ammotype_t.am_cell,
	statenum_t.S_BFGUP,
	statenum_t.S_BFGDOWN,
	statenum_t.S_BFG,
	statenum_t.S_BFG1,
	statenum_t.S_BFGFLASH1
    ),
    new weaponinfo_t(
	// chainsaw
        ammotype_t.am_noammo,
	statenum_t.S_SAWUP,
	statenum_t.S_SAWDOWN,
	statenum_t.S_SAW,
	statenum_t.S_SAW1,
	statenum_t.S_NULL
    ),
    new weaponinfo_t(
	// super shotgun
    ammotype_t.am_shell,
    statenum_t.S_DSGUNUP,
	statenum_t.S_DSGUNDOWN,
	statenum_t.S_DSGUN,
	statenum_t.S_DSGUN1,
	statenum_t.S_DSGUNFLASH1
    )
    };
}









package doom;

public enum gameaction_t {
        ga_nothing,
        ga_loadlevel,
        ga_newgame,
        ga_loadgame,
        ga_savegame,
        ga_playdemo,
        ga_completed,
        ga_victory,
        ga_worlddone,
        ga_screenshot,
        ga_failure // HACK: communicate failures silently
    }

package doom;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: englsh.java,v 1.5 2011/05/31 21:46:20 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//  Printed strings for translation.
//  English language support (default).
//
//-----------------------------------------------------------------------------

//
//  Printed strings for translation
//

//
// D_Main.C
//

public class englsh{
public final static String  D_DEVSTR="Development mode ON.\n";
public final static String  D_CDROM="CD-ROM Version: default.cfg from c:\\doomdata\n";

//
//  M_Menu.C
//
public final static String  PRESSKEY ="press a key.";
public final static String  PRESSYN ="press y or n.";
public final static String  QUITMSG="are you sure you want to\nquit this great game?";
public final static String  LOADNET ="you can't do load while in a net game!\n\n"+PRESSKEY;
public final static String  QLOADNET="you can't quickload during a netgame!\n\n"+PRESSKEY;
public final static String  QSAVESPOT="you haven't picked a quicksave slot yet!\n\n"+PRESSKEY;
public final static String  SAVEDEAD ="you can't save if you aren't playing!\n\n"+PRESSKEY;
public final static String  QSPROMPT ="quicksave over your game named\n\n'%s'?\n\n"+PRESSYN;
public final static String  QLPROMPT="do you want to quickload the game named\n\n'%s'?\n\n"+PRESSYN;

public final static String  NEWGAME = "you can't start a new game\nwhile in a network game.\n\n"+PRESSKEY;

public final static String  NIGHTMARE ="are you sure? this skill level\nisn't even remotely fair.\n\n"+PRESSYN;

public final static String  SWSTRING = "this is the shareware version of doom.\n\nyou need to order the entire trilogy.\n\n"+PRESSKEY;

public final static String  MSGOFF="Messages OFF";
public final static String  MSGON   ="Messages ON";
public final static String  NETEND="you can't end a netgame!\n\n"+PRESSKEY;
public final static String  ENDGAME="are you sure you want to end the game?\n\n"+PRESSYN;

public final static String  DOSY    ="(press y to quit)";

public final static String  DETAILHI="High detail";
public final static String  DETAILLO="Low detail";
public final static String  GAMMALVL0="Gamma correction OFF";
public final static String  GAMMALVL1="Gamma correction level 1";
public final static String  GAMMALVL2="Gamma correction level 2";
public final static String  GAMMALVL3="Gamma correction level 3";
public final static String  GAMMALVL4="Gamma correction level 4";
public final static String  EMPTYSTRING="empty slot";

//
//  P_inter.C
//
public final static String  GOTARMOR="Picked up the armor.";
public final static String  GOTMEGA="Picked up the MegaArmor!";
public final static String  GOTHTHBONUS="Picked up a health bonus.";
public final static String  GOTARMBONUS="Picked up an armor bonus.";
public final static String  GOTSTIM="Picked up a stimpack.";
public final static String  GOTMEDINEED="Picked up a medikit that you REALLY need!";
public final static String  GOTMEDIKIT="Picked up a medikit.";
public final static String  GOTSUPER="Supercharge!";

public final static String  GOTBLUECARD="Picked up a blue keycard.";
public final static String  GOTYELWCARD="Picked up a yellow keycard.";
public final static String  GOTREDCARD="Picked up a red keycard.";
public final static String  GOTBLUESKUL="Picked up a blue skull key.";
public final static String  GOTYELWSKUL="Picked up a yellow skull key.";
public final static String  GOTREDSKULL="Picked up a red skull key.";

public final static String  GOTINVUL="Invulnerability!";
public final static String  GOTBERSERK="Berserk!";
public final static String  GOTINVIS="Partial Invisibility";
public final static String  GOTSUIT="Radiation Shielding Suit";
public final static String  GOTMAP="Computer Area Map";
public final static String  GOTVISOR="Light Amplification Visor";
public final static String  GOTMSPHERE="MegaSphere!";

public final static String  GOTCLIP="Picked up a clip.";
public final static String  GOTCLIPBOX="Picked up a box of bullets.";
public final static String  GOTROCKET="Picked up a rocket.";
public final static String  GOTROCKBOX="Picked up a box of rockets.";
public final static String  GOTCELL="Picked up an energy cell.";
public final static String  GOTCELLBOX="Picked up an energy cell pack.";
public final static String  GOTSHELLS="Picked up 4 shotgun shells.";
public final static String  GOTSHELLBOX="Picked up a box of shotgun shells.";
public final static String  GOTBACKPACK="Picked up a backpack full of ammo!";

public final static String  GOTBFG9000="You got the BFG9000!  Oh, yes.";
public final static String  GOTCHAINGUN="You got the chaingun!";
public final static String  GOTCHAINSAW="A chainsaw!  Find some meat!";
public final static String  GOTLAUNCHER="You got the rocket launcher!";
public final static String  GOTPLASMA="You got the plasma gun!";
public final static String  GOTSHOTGUN="You got the shotgun!";
public final static String  GOTSHOTGUN2="You got the super shotgun!";

//
// P_Doors.C
//
public final static String  PD_BLUEO="You need a blue key to activate this object";
public final static String  PD_REDO="You need a red key to activate this object";
public final static String  PD_YELLOWO="You need a yellow key to activate this object";
public final static String  PD_BLUEK="You need a blue key to open this door";
public final static String  PD_REDK="You need a red key to open this door";
public final static String  PD_YELLOWK="You need a yellow key to open this door";

//
//  G_game.C
//
public final static String  GGSAVED="game saved.";

//
//  HU_stuff.C
//
public final static String  HUSTR_MSGU="[Message unsent]";

public final static String  HUSTR_E1M1="E1M1: Hangar";
public final static String  HUSTR_E1M2="E1M2: Nuclear Plant";
public final static String  HUSTR_E1M3="E1M3: Toxin Refinery";
public final static String  HUSTR_E1M4="E1M4: Command Control";
public final static String  HUSTR_E1M5="E1M5: Phobos Lab";
public final static String  HUSTR_E1M6="E1M6: Central Processing";
public final static String  HUSTR_E1M7="E1M7: Computer Station";
public final static String  HUSTR_E1M8="E1M8: Phobos Anomaly";
public final static String  HUSTR_E1M9="E1M9: Military Base";

public final static String  HUSTR_E2M1="E2M1: Deimos Anomaly";
public final static String  HUSTR_E2M2="E2M2: Containment Area";
public final static String  HUSTR_E2M3="E2M3: Refinery";
public final static String  HUSTR_E2M4="E2M4: Deimos Lab";
public final static String  HUSTR_E2M5="E2M5: Command Center";
public final static String  HUSTR_E2M6="E2M6: Halls of the Damned";
public final static String  HUSTR_E2M7="E2M7: Spawning Vats";
public final static String  HUSTR_E2M8="E2M8: Tower of Babel";
public final static String  HUSTR_E2M9="E2M9: Fortress of Mystery";

public final static String  HUSTR_E3M1="E3M1: Hell Keep";
public final static String  HUSTR_E3M2="E3M2: Slough of Despair";
public final static String  HUSTR_E3M3="E3M3: Pandemonium";
public final static String  HUSTR_E3M4="E3M4: House of Pain";
public final static String  HUSTR_E3M5="E3M5: Unholy Cathedral";
public final static String  HUSTR_E3M6="E3M6: Mt. Erebus";
public final static String  HUSTR_E3M7="E3M7: Limbo";
public final static String  HUSTR_E3M8="E3M8: Dis";
public final static String  HUSTR_E3M9="E3M9: Warrens";

public final static String  HUSTR_E4M1="E4M1: Hell Beneath";
public final static String  HUSTR_E4M2="E4M2: Perfect Hatred";
public final static String  HUSTR_E4M3="E4M3: Sever The Wicked";
public final static String  HUSTR_E4M4="E4M4: Unruly Evil";
public final static String  HUSTR_E4M5="E4M5: They Will Repent";
public final static String  HUSTR_E4M6="E4M6: Against Thee Wickedly";
public final static String  HUSTR_E4M7="E4M7: And Hell Followed";
public final static String  HUSTR_E4M8="E4M8: Unto The Cruel";
public final static String  HUSTR_E4M9="E4M9: Fear";

public final static String  HUSTR_1="level 1: entryway";
public final static String  HUSTR_2="level 2: underhalls";
public final static String  HUSTR_3="level 3: the gantlet";
public final static String  HUSTR_4="level 4: the focus";
public final static String  HUSTR_5="level 5: the waste tunnels";
public final static String  HUSTR_6="level 6: the crusher";
public final static String  HUSTR_7="level 7: dead simple";
public final static String  HUSTR_8="level 8: tricks and traps";
public final static String  HUSTR_9="level 9: the pit";
public final static String  HUSTR_10="level 10: refueling base";
public final static String  HUSTR_11="level 11: 'o' of destruction!";

public final static String  HUSTR_12="level 12: the factory";
public final static String  HUSTR_13="level 13: downtown";
public final static String  HUSTR_14="level 14: the inmost dens";
public final static String  HUSTR_15="level 15: industrial zone";
public final static String  HUSTR_16="level 16: suburbs";
public final static String  HUSTR_17="level 17: tenements";
public final static String  HUSTR_18="level 18: the courtyard";
public final static String  HUSTR_19="level 19: the citadel";
public final static String  HUSTR_20="level 20: gotcha!";

public final static String  HUSTR_21="level 21: nirvana";
public final static String  HUSTR_22="level 22: the catacombs";
public final static String  HUSTR_23="level 23: barrels o' fun";
public final static String  HUSTR_24="level 24: the chasm";
public final static String  HUSTR_25="level 25: bloodfalls";
public final static String  HUSTR_26="level 26: the abandoned mines";
public final static String  HUSTR_27="level 27: monster condo";
public final static String  HUSTR_28="level 28: the spirit world";
public final static String  HUSTR_29="level 29: the living end";
public final static String  HUSTR_30="level 30: icon of sin";

public final static String  HUSTR_31="level 31: wolfenstein";
public final static String  HUSTR_32="level 32: grosse";
public final static String  HUSTR_33="level 33: betray";

public final static String  PHUSTR_1="level 1: congo";
public final static String  PHUSTR_2="level 2: well of souls";
public final static String  PHUSTR_3="level 3: aztec";
public final static String  PHUSTR_4="level 4: caged";
public final static String  PHUSTR_5="level 5: ghost town";
public final static String  PHUSTR_6="level 6: baron's lair";
public final static String  PHUSTR_7="level 7: caughtyard";
public final static String  PHUSTR_8="level 8: realm";
public final static String  PHUSTR_9="level 9: abattoire";
public final static String  PHUSTR_10="level 10: onslaught";
public final static String  PHUSTR_11="level 11: hunted";

public final static String  PHUSTR_12="level 12: speed";
public final static String  PHUSTR_13="level 13: the crypt";
public final static String  PHUSTR_14="level 14: genesis";
public final static String  PHUSTR_15="level 15: the twilight";
public final static String  PHUSTR_16="level 16: the omen";
public final static String  PHUSTR_17="level 17: compound";
public final static String  PHUSTR_18="level 18: neurosphere";
public final static String  PHUSTR_19="level 19: nme";
public final static String  PHUSTR_20="level 20: the death domain";

public final static String  PHUSTR_21="level 21: slayer";
public final static String  PHUSTR_22="level 22: impossible mission";
public final static String  PHUSTR_23="level 23: tombstone";
public final static String  PHUSTR_24="level 24: the final frontier";
public final static String  PHUSTR_25="level 25: the temple of darkness";
public final static String  PHUSTR_26="level 26: bunker";
public final static String  PHUSTR_27="level 27: anti-christ";
public final static String  PHUSTR_28="level 28: the sewers";
public final static String  PHUSTR_29="level 29: odyssey of noises";
public final static String  PHUSTR_30="level 30: the gateway of hell";

public final static String  PHUSTR_31="level 31: cyberden";
public final static String  PHUSTR_32="level 32: go 2 it";

public final static String  THUSTR_1="level 1: system control";
public final static String  THUSTR_2="level 2: human bbq";
public final static String  THUSTR_3="level 3: power control";
public final static String  THUSTR_4="level 4: wormhole";
public final static String  THUSTR_5="level 5: hanger";
public final static String  THUSTR_6="level 6: open season";
public final static String  THUSTR_7="level 7: prison";
public final static String  THUSTR_8="level 8: metal";
public final static String  THUSTR_9="level 9: stronghold";
public final static String  THUSTR_10="level 10: redemption";
public final static String  THUSTR_11="level 11: storage facility";

public final static String  THUSTR_12="level 12: crater";
public final static String  THUSTR_13="level 13: nukage processing";
public final static String  THUSTR_14="level 14: steel works";
public final static String  THUSTR_15="level 15: dead zone";
public final static String  THUSTR_16="level 16: deepest reaches";
public final static String  THUSTR_17="level 17: processing area";
public final static String  THUSTR_18="level 18: mill";
public final static String  THUSTR_19="level 19: shipping/respawning";
public final static String  THUSTR_20="level 20: central processing";

public final static String  THUSTR_21="level 21: administration center";
public final static String  THUSTR_22="level 22: habitat";
public final static String  THUSTR_23="level 23: lunar mining project";
public final static String  THUSTR_24="level 24: quarry";
public final static String  THUSTR_25="level 25: baron's den";
public final static String  THUSTR_26="level 26: ballistyx";
public final static String  THUSTR_27="level 27: mount pain";
public final static String  THUSTR_28="level 28: heck";
public final static String  THUSTR_29="level 29: river styx";
public final static String  THUSTR_30="level 30: last call";

public final static String  THUSTR_31="level 31: pharaoh";
public final static String  THUSTR_32="level 32: caribbean";

public final static String  HUSTR_CHATMACRO1="I'm ready to kick butt!";
public final static String  HUSTR_CHATMACRO2="I'm OK.";
public final static String  HUSTR_CHATMACRO3="I'm not looking too good!";
public final static String  HUSTR_CHATMACRO4="Help!";
public final static String  HUSTR_CHATMACRO5="You suck!";
public final static String  HUSTR_CHATMACRO6="Next time, scumbag...";
public final static String  HUSTR_CHATMACRO7="Come here!";
public final static String  HUSTR_CHATMACRO8="I'll take care of it.";
public final static String  HUSTR_CHATMACRO9="Yes";
public final static String  HUSTR_CHATMACRO0="No";

public final static String  HUSTR_TALKTOSELF1="You mumble to yourself";
public final static String  HUSTR_TALKTOSELF2="Who's there?";
public final static String  HUSTR_TALKTOSELF3="You scare yourself";
public final static String  HUSTR_TALKTOSELF4="You start to rave";
public final static String  HUSTR_TALKTOSELF5="You've lost it...";

public final static String  HUSTR_MESSAGESENT="[Message Sent]";

// The following should NOT be changed unless it seems
// just AWFULLY necessary

public final static String  HUSTR_PLRGREEN="Green: ";
public final static String  HUSTR_PLRINDIGO="Indigo: ";
public final static String  HUSTR_PLRBROWN="Brown: ";
public final static String  HUSTR_PLRRED    ="Red: ";

public final static char  HUSTR_KEYGREEN = 'g';
public final static char  HUSTR_KEYINDIGO ='i';
public final static char  HUSTR_KEYBROWN = 'b';
public final static char  HUSTR_KEYRED   = 'r';

//
//  AM_map.C
//

public final static String  AMSTR_FOLLOWON="Follow Mode ON";
public final static String  AMSTR_FOLLOWOFF="Follow Mode OFF";

public final static String  AMSTR_GRIDON="Grid ON";
public final static String  AMSTR_GRIDOFF="Grid OFF";

public final static String  AMSTR_MARKEDSPOT="Marked Spot";
public final static String  AMSTR_MARKSCLEARED="All Marks Cleared";

//
//  ST_stuff.C
//

public final static String  STSTR_MUS   ="Music Change";
public final static String  STSTR_NOMUS ="IMPOSSIBLE SELECTION";
public final static String  STSTR_DQDON ="Degreelessness Mode On";
public final static String  STSTR_DQDOFF="Degreelessness Mode Off";

public final static String  STSTR_KFAADDED="Very Happy Ammo Added";
public final static String  STSTR_FAADDED="Ammo (no keys) Added";

public final static String  STSTR_NCON  ="No Clipping Mode ON";
public final static String  STSTR_NCOFF ="No Clipping Mode OFF";

public final static String  STSTR_BEHOLD="inVuln, Str, Inviso, Rad, Allmap, or Lite-amp";
public final static String  STSTR_BEHOLDX="Power-up Toggled";

public final static String  STSTR_CHOPPERS="... doesn't suck - GM";
public final static String  STSTR_CLEV  ="Changing Level...";

//
//  F_Finale.C
//
public final static String  E1TEXT =(
"Once you beat the big badasses and\n"+
"clean out the moon base you're supposed\n"+
"to win, aren't you? Aren't you? Where's\n"+
"your fat reward and ticket home? What\n"+
"the hell is this? It's not supposed to\n"+
"end this way!\n"+
"\n" +
"It stinks like rotten meat, but looks\n"+
"like the lost Deimos base.  Looks like\n"+
"you're stuck on The Shores of Hell.\n"+
"The only way out is through.\n"+
"\n"+
"To continue the DOOM experience, play\n"+
"The Shores of Hell and its amazing\n"+
"sequel, Inferno!\n");


public final static String  E2TEXT =(
"You've done it! The hideous cyber-\n"+
"demon lord that ruled the lost Deimos\n"+
"moon base has been slain and you\n"+
"are triumphant! But ... where are\n"+
"you? You clamber to the edge of the\n"+
"moon and look down to see the awful\n"+
"truth.\n" +
"\n"+
"Deimos floats above Hell itself!\n"+
"You've never heard of anyone escaping\n"+
"from Hell, but you'll make the bastards\n"+
"sorry they ever heard of you! Quickly,\n"+
"you rappel down to  the surface of\n"+
"Hell.\n"+
"\n" +
"Now, it's on to the final chapter of\n"+
"DOOM! -- Inferno.");


public final static String  E3TEXT =(
"The loathsome spiderdemon that\n"+
"masterminded the invasion of the moon\n"+
"bases and caused so much death has had\n"+
"its ass kicked for all time.\n"+
"\n"+
"A hidden doorway opens and you enter.\n"+
"You've proven too tough for Hell to\n"+
"contain, and now Hell at last plays\n"+
"fair -- for you emerge from the door\n"+
"to see the green fields of Earth!\n"+
"Home at last.\n" +
"\n"+
"You wonder what's been happening on\n"+
"Earth while you were battling evil\n"+
"unleashed. It's good that no Hell-\n"+
"spawn could have come through that\n"+
"door with you ...");


public final static String  E4TEXT =(
"the spider mastermind must have sent forth\n"+
"its legions of hellspawn before your\n"+
"final confrontation with that terrible\n"+
"beast from hell.  but you stepped forward\n"+
"and brought forth eternal damnation and\n"+
"suffering upon the horde as a true hero\n"+
"would in the face of something so evil.\n"+
"\n"+
"besides, someone was gonna pay for what\n"+
"happened to daisy, your pet rabbit.\n"+
"\n"+
"but now, you see spread before you more\n"+
"potential pain and gibbitude as a nation\n"+
"of demons run amok among our cities.\n"+
"\n"+
"next stop, hell on earth!");


// after level 6, put this:

public final static String  C1TEXT =(
"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" +
"STARPORT. BUT SOMETHING IS WRONG. THE\n" +
"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" +
"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" +
"IS BEING SUBVERTED BY THEIR PRESENCE.\n" +
"\n"+
"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" +
"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" +
"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" +
"OF THE STARBASE AND FIND THE CONTROLLING\n" +
"SWITCH WHICH HOLDS EARTH'S POPULATION\n" +
"HOSTAGE.");

// After level 11, put this:

public final static String  C2TEXT =(
"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" +
"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"+
"THE NIGHTMARE.  NOW YOU ARE THE ONLY\n"+
"HUMAN LEFT ON THE FACE OF THE PLANET.\n"+
"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"+
"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"+
"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"+
"THAT YOU HAVE SAVED YOUR SPECIES.\n"+
"\n"+
"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"+
"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"+
"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"+
"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"+
"ENTRY.  THE ALIEN BASE IS IN THE HEART OF\n"+
"YOUR OWN HOME CITY, NOT FAR FROM THE\n"+
"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"+
"UP AND RETURN TO THE FRAY.");


// After level 20, put this:

public final static String  C3TEXT =(
"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"+
"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"+
"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"+
"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"+
"TEETH AND PLUNGE THROUGH IT.\n"+
"\n"+
"THERE MUST BE A WAY TO CLOSE IT ON THE\n"+
"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"+
"GOT TO GO THROUGH HELL TO GET TO IT?");


// After level 29, put this:

public final static String  C4TEXT =(
"THE HORRENDOUS VISAGE OF THE BIGGEST\n"+
"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"+
"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"+
"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"+
"UP AND DIES, ITS THRASHING LIMBS\n"+
"DEVASTATING UNTOLD MILES OF HELL'S\n"+
"SURFACE.\n"+
"\n"+
"YOU'VE DONE IT. THE INVASION IS OVER.\n"+
"EARTH IS SAVED. HELL IS A WRECK. YOU\n"+
"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"+
"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"+
"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"+
"HOME. REBUILDING EARTH OUGHT TO BE A\n"+
"LOT MORE FUN THAN RUINING IT WAS.\n");



// Before level 31, put this:

public final static String  C5TEXT =(
"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"+
"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"+
"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"+
"WHO THE INMATES OF THIS CORNER OF HELL\n"+
"WILL BE.");


// Before level 32, put this:

public final static String  C6TEXT =(
"CONGRATULATIONS, YOU'VE FOUND THE\n"+
"SUPER SECRET LEVEL!  YOU'D BETTER\n"+
"BLAZE THROUGH THIS ONE!\n");


// after map 06 

public final static String  P1TEXT  =(
"You gloat over the steaming carcass of the\n"+
"Guardian.  With its death, you've wrested\n"+
"the Accelerator from the stinking claws\n"+
"of Hell.  You relax and glance around the\n"+
"room.  Damn!  There was supposed to be at\n"+
"least one working prototype, but you can't\n"+
"see it. The demons must have taken it.\n"+
"\n"+
"You must find the prototype, or all your\n"+
"struggles will have been wasted. Keep\n"+
"moving, keep fighting, keep killing.\n"+
"Oh yes, keep living, too.");


// after map 11

public final static String  P2TEXT =(
"Even the deadly Arch-Vile labyrinth could\n"+
"not stop you, and you've gotten to the\n"+
"prototype Accelerator which is soon\n"+
"efficiently and permanently deactivated.\n"+
"\n"+
"You're good at that kind of thing.");


// after map 20

public final static String  P3TEXT =(
"You've bashed and battered your way into\n"+
"the heart of the devil-hive.  Time for a\n"+
"Search-and-Destroy mission, aimed at the\n"+
"Gatekeeper, whose foul offspring is\n"+
"cascading to Earth.  Yeah, he's bad. But\n"+
"you know who's worse!\n"+
"\n"+
"Grinning evilly, you check your gear, and\n"+
"get ready to give the bastard a little Hell\n"+
"of your own making!");

// after map 30

public final static String  P4TEXT =(
"The Gatekeeper's evil face is splattered\n"+
"all over the place.  As its tattered corpse\n"+
"collapses, an inverted Gate forms and\n"+
"sucks down the shards of the last\n"+
"prototype Accelerator, not to mention the\n"+
"few remaining demons.  You're done. Hell\n"+
"has gone back to pounding bad dead folks \n"+
"instead of good live ones.  Remember to\n"+
"tell your grandkids to put a rocket\n"+
"launcher in your coffin. If you go to Hell\n"+
"when you die, you'll need it for some\n"+
"final cleaning-up ...");

// before map 31

public final static String  P5TEXT =(
"You've found the second-hardest level we\n"+
"got. Hope you have a saved game a level or\n"+
"two previous.  If not, be prepared to die\n"+
"aplenty. For master marines only.");

// before map 32

public final static String  P6TEXT =(
"Betcha wondered just what WAS the hardest\n"+
"level we had ready for ya?  Now you know.\n"+
"No one gets out alive.");


public final static String  T1TEXT =(
"You've fought your way out of the infested\n"+
"experimental labs.   It seems that UAC has\n"+
"once again gulped it down.  With their\n"+
"high turnover, it must be hard for poor\n"+
"old UAC to buy corporate health insurance\n"+
"nowadays..\n"+
"\n"+
"Ahead lies the military complex, now\n"+
"swarming with diseased horrors hot to get\n"+
"their teeth into you. With luck, the\n"+
"complex still has some warlike ordnance\n"+
"laying around.");


public final static String  T2TEXT =(
"You hear the grinding of heavy machinery\n"+
"ahead.  You sure hope they're not stamping\n"+
"out new hellspawn, but you're ready to\n"+
"ream out a whole herd if you have to.\n"+
"They might be planning a blood feast, but\n"+
"you feel about as mean as two thousand\n"+
"maniacs packed into one mad killer.\n"+
"\n"+
"You don't plan to go down easy.");


public final static String  T3TEXT =(
"The vista opening ahead looks real damn\n"+
"familiar. Smells familiar, too -- like\n"+
"fried excrement. You didn't like this\n"+
"place before, and you sure as hell ain't\n"+
"planning to like it now. The more you\n"+
"brood on it, the madder you get.\n"+
"Hefting your gun, an evil grin trickles\n"+
"onto your face. Time to take some names.");

public final static String  T4TEXT =(
"Suddenly, all is silent, from one horizon\n"+
"to the other. The agonizing echo of Hell\n"+
"fades away, the nightmare sky turns to\n"+
"blue, the heaps of monster corpses start \n"+
"to evaporate along with the evil stench \n"+
"that filled the air. Jeeze, maybe you've\n"+
"done it. Have you really won?\n"+
"\n"+
"Something rumbles in the distance.\n"+
"A blue light begins to glow inside the\n"+
"ruined skull of the demon-spitter.");


public final static String  T5TEXT =(
"What now? Looks totally different. Kind\n"+
"of like King Tut's condo. Well,\n"+
"whatever's here can't be any worse\n"+
"than usual. Can it?  Or maybe it's best\n"+
"to let sleeping gods lie..");


public final static String  T6TEXT =(
"Time for a vacation. You've burst the\n"+
"bowels of hell and by golly you're ready\n"+
"for a break. You mutter to yourself,\n"+
"Maybe someone else can kick Hell's ass\n"+
"next time around. Ahead lies a quiet town,\n"+
"with peaceful flowing water, quaint\n"+
"buildings, and presumably no Hellspawn.\n"+
"\n"+
"As you step off the transport, you hear\n"+
"the stomp of a cyberdemon's iron shoe.");



//
// Character cast strings F_FINALE.C
//
public final static String  CC_ZOMBIE="ZOMBIEMAN";
public final static String  CC_SHOTGUN="SHOTGUN GUY";
public final static String  CC_HEAVY="HEAVY WEAPON DUDE";
public final static String  CC_IMP="IMP";
public final static String  CC_DEMON="DEMON";
public final static String  CC_LOST="LOST SOUL";
public final static String  CC_CACO="CACODEMON";
public final static String  CC_HELL="HELL KNIGHT";
public final static String  CC_BARON="BARON OF HELL";
public final static String  CC_ARACH="ARACHNOTRON";
public final static String  CC_PAIN="PAIN ELEMENTAL";
public final static String  CC_REVEN="REVENANT";
public final static String  CC_MANCU="MANCUBUS";
public final static String  CC_ARCH="ARCH-VILE";
public final static String  CC_SPIDER="THE SPIDER MASTERMIND";
public final static String  CC_CYBER="THE CYBERDEMON";
public final static String  CC_NAZI="WAFFEN SS. SIEG HEIL!";
public final static String  CC_KEEN="COMMANDER KEEN";
public final static String  CC_BARREL="EXPLODING BARREL";
public final static String  CC_HERO="OUR HERO";

}
package doom;

import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import w.CacheableDoomObject;
import w.IReadableDoomObject;

public class ticcmd_t implements IDatagramSerializable, IReadableDoomObject,CacheableDoomObject{
    
    // The length datagrams are supposed to have, for full compatibility.
    
    public static final int TICCMDLEN=8;
    
    // Initializes ticcmd buffer, too.
    
    public ticcmd_t(){
        this.buffer=new byte[TICCMDLEN];
    }
    
    /** *2048 for move */
    public byte forwardmove;

    /** *2048 for move */
    public byte sidemove;

    /** <<16 for angle delta */
    public short angleturn;

    /** checks for net game */
    public short consistancy;
    
    /** MAES: these are unsigned bytes :-( 
     *  However over networks, if we wish for vanilla compatibility,
     *  these must be reduced to 8-bit "chars"
     * */

    public char chatchar, buttons; 
    
    /** HERETIC look/fly up/down/centering */    
    public char		lookfly; 
    
    // TODO: will be ignored during vanilla demos. Consider using specialized
    // per-demotype readers instead of Cacheable/Unpackage.

    /** replaces G_CmdChecksum (ticcmd_t cmd) */

    /////////////////////////////////////////////
    
    // For datagram serialization
    private byte[] buffer;
    
    public int getChecksum(ticcmd_t cmd) {
        int sum = 0;
        sum += forwardmove;
        sum += sidemove;
        sum += angleturn;
        sum += consistancy;
        sum += chatchar;
        sum += buttons;
        return sum;
        }

    /** because Cloneable is bullshit */
    
     public void copyTo(ticcmd_t dest){
         dest.forwardmove = forwardmove;
         dest.sidemove = sidemove;
         dest.angleturn= angleturn;
         dest.consistancy= consistancy;
         dest.chatchar= chatchar;
         dest.buttons= buttons;
         dest.lookfly=lookfly;
     }
     
     private static StringBuilder sb=new StringBuilder();
     
     public String toString(){
         sb.setLength(0);
         sb.append(" forwardmove ");
         sb.append(Integer.toHexString(this.forwardmove)); 
         sb.append(" sidemove ");
         sb.append(Integer.toHexString(this.sidemove)); 
         sb.append(" angleturn ");
         sb.append(Integer.toHexString(this.angleturn)); 
         sb.append(" consistancy ");
         sb.append(Integer.toHexString(this.consistancy));      
         sb.append(" chatchar ");
         sb.append(chatchar);         
        sb.append(" buttons ");
         sb.append(Integer.toHexString(this.buttons));
         return sb.toString();
     }

    @Override
    public byte[] pack() {
        buffer[0]=forwardmove;
        buffer[1]=sidemove;        
        buffer[2]=(byte) (angleturn>>>8);
        buffer[3]=(byte) (angleturn&0x00FF);
        buffer[4]=(byte) (consistancy>>>8);
        buffer[5]=(byte) (consistancy&0x00FF);

        // We only send 8 bytes because the original length was 8 bytes.
        buffer[6]=(byte) (chatchar&0x00FF);
        buffer[7]=(byte) (buttons&0x00FF);
        
        return buffer;
    }

    @Override
    public void pack(byte[] buf, int offset) {
        buf[0+offset]=forwardmove;
        buf[1+offset]=sidemove;        
        buf[2+offset]=(byte) (angleturn>>>8);
        buf[3+offset]=(byte) (angleturn&0x00FF);
        buf[4+offset]=(byte) (consistancy>>>8);
        buf[5+offset]=(byte) (consistancy&0x00FF);

        // We only send 8 bytes because the original length was 8 bytes.
        buf[6+offset]=(byte) (chatchar&0x00FF);
        buf[7+offset]=(byte) (buttons&0x00FF);
        
    }

    @Override
    public void unpack(byte[] buf) {
        unpack(buf,0);        
        }

    @Override
    public void unpack(byte[] buf, int offset) {
        forwardmove=buf[0+offset];
        sidemove=   buf[1+offset];        
        angleturn=(short)(buf[2+offset]<<8|buf[3+offset]);
        consistancy=(short)(buf[4+offset]<<8|buf[5+offset]);
        // We blow these up to full chars.
        chatchar=(char)(0x00FF& buf[6+offset]);
        buttons=(char) (0x00FF& buf[7+offset]);
        
    }

    @Override
    public byte[] cached() {
        return this.buffer;
    }

    @Override
    public void read(DataInputStream f)
            throws IOException {
    	iobuffer.position(0);
    	iobuffer.order(ByteOrder.LITTLE_ENDIAN);
    	f.read(iobuffer.array());
    	unpack(iobuffer);
    }
    
    /** This is useful only when loading/saving players from savegames.
     *  It's NOT interchangeable with datagram methods, because it
     *  does not use the network byte order.
     */

    @Override
    public void unpack(ByteBuffer f)
            throws IOException {
        f.order(ByteOrder.LITTLE_ENDIAN);
        forwardmove=f.get();
        sidemove=   f.get();        
        // Even if they use the "unsigned char" syntax, angleturn is signed.
        angleturn=f.getShort();
        consistancy=f.getShort();
        // We blow these up to full chars.
        chatchar=(char) f.get();
        buttons=(char) f.get();
        
    }
    
    /** Ditto, we only pack some of the fields.
     * 
     * @param f
     * @throws IOException
     */
    public void pack(ByteBuffer f)
            throws IOException {
        f.order(ByteOrder.LITTLE_ENDIAN);
        f.put(forwardmove);
        f.put(sidemove);        
        // LE order on disk for vanilla compatibility.
        f.putShort(angleturn);
        f.putShort(consistancy);
        // We crimp these to bytes :-(
        f.put((byte) chatchar);
        f.put((byte) buttons);     
    }
    
    private static ByteBuffer iobuffer=ByteBuffer.allocate(8);
    
};

package doom;


//
// INTERMISSION
// Structure passed e.g. to WI_Start(wb)
//

public class wbplayerstruct_t implements Cloneable{
    
    public wbplayerstruct_t(){
        frags=new int[4];
    }
     public boolean in; // whether the player is in game
     
     /** Player stats, kills, collected items etc. */
     public int     skills;
     public int     sitems;
     public int     ssecret;
     public int     stime; 
     public int[]   frags;
     /** current score on entry, modified on return */
     public int     score;
   
     public wbplayerstruct_t clone(){
         wbplayerstruct_t r=null;
        try {
            r = (wbplayerstruct_t)super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
         /*r.in=this.in;
         r.skills=this.skills;
         r.sitems=this.sitems;
         r.ssecret=this.ssecret;
         r.stime=this.stime; */
         System.arraycopy(this.frags, 0, r.frags,0,r.frags.length);
         // r.score=this.score;
         
         
        return r;
         
     }
     
 }

package doom;

import static data.Limits.MAXPLAYERS;
import utils.C2JUtils;

public class wbstartstruct_t implements Cloneable{

        public wbstartstruct_t(){
            plyr=new wbplayerstruct_t[MAXPLAYERS];
            C2JUtils.initArrayOfObjects(plyr, wbplayerstruct_t.class);
        }
    
        public int      epsd;   // episode # (0-2)

        // if true, splash the secret level
        public boolean  didsecret;
        
        // previous and next levels, origin 0
        public int      last;
        public int      next;   
        
        public int      maxkills;
        public int      maxitems;
        public int      maxsecret;
        public int      maxfrags;

        /** the par time */
        public int      partime;
        
        /** index of this player in game */
        public int      pnum;   
        /** meant to be treated as a "struct", therefore assignments should be deep copies */
        public wbplayerstruct_t[]   plyr;
        
        public wbstartstruct_t clone(){
            wbstartstruct_t cl=null;
            try {
                cl=(wbstartstruct_t)super.clone();
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            /*cl.epsd=this.epsd;
            cl.didsecret=this.didsecret;
            cl.last=this.last;
            cl.next=this.next;
            cl.maxfrags=this.maxfrags;
            cl.maxitems=this.maxitems;
            cl.maxsecret=this.maxsecret;
            cl.maxkills=this.maxkills;
            cl.partime=this.partime;
            cl.pnum=this.pnum;*/
            for (int i=0;i<cl.plyr.length;i++){
                cl.plyr[i]=this.plyr[i].clone();    
            }
            //cl.plyr=this.plyr.clone();
            
            return cl;
            
        }
        
    } 

package doom;

import java.io.IOException;

/** Stuff that the "main" is supposed to do. DoomMain implements those.
 * 
 * @author Maes
 *
 */


public interface IDoom {


	/** Called by IO functions when input is detected. */
	void PostEvent (event_t ev);
	void PageTicker ();
	void PageDrawer ();
	void AdvanceDemo ();
	void StartTitle ();
    void QuitNetGame() throws IOException; 

}
package doom;

 // Player states.
 //
 public enum  playerstate_t
 {
     // Playing or camping.
     PST_LIVE,
     // Dead on the ground, view follows killer.
     PST_DEAD,
     // Ready to restart/respawn???
     PST_REBORN      

 };
package n;

import i.DoomStatusAware;
import i.IDoomSystem;
import doom.DoomMain;
import doom.DoomStatus;
import doom.IDoomGameNetworking;
import doom.NetConsts;
import doom.doomcom_t;

/** Does nothing.
 *  Allows running single-player games without an actual network.
 *  Hopefully, it will be replaced by a real UDP-based driver one day.
 *  
 * @author Velktron
 *
 */

public class DummyNetworkDriver implements NetConsts,DoomSystemNetworking, DoomStatusAware{

	////////////// STATUS ///////////

	IDoomSystem I;
	DoomMain DM;
	IDoomGameNetworking DGN;

	public DummyNetworkDriver(DoomStatus DC){
		updateStatus(DC);
	}

	@Override
	public void InitNetwork() {
		doomcom_t doomcom =new doomcom_t();
		doomcom.id=DOOMCOM_ID;
		doomcom.ticdup=1;

		// single player game
		DM.netgame = false;
		doomcom.id = DOOMCOM_ID;
		doomcom.numplayers = doomcom.numnodes = 1;
		doomcom.deathmatch = 0;
		doomcom.consoleplayer = 0;
		DGN.setDoomCom(doomcom);
	}

	@Override
	public void NetCmd() {
		// TODO Auto-generated method stub

	}

	@Override
	public void updateStatus(DoomStatus DC) {
		this.DM=DC.DM;
		this.DGN=DC.DM;
	}

}

package n;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: DoomSystemNetworking.java,v 1.1 2010/11/17 23:55:06 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//  System specific network interface stuff.
//
//-----------------------------------------------------------------------------

public interface DoomSystemNetworking{


// Called by D_DoomMain.

public void InitNetwork ();
public void NetCmd ();


}

//-----------------------------------------------------------------------------
//
// $Log: DoomSystemNetworking.java,v $
// Revision 1.1  2010/11/17 23:55:06  velktron
// Kind of playable/controllable.
//
// Revision 1.1  2010/10/22 16:22:43  velktron
// Renderer works stably enough but a ton of bleeding. Started working on netcode.
//
//
//-----------------------------------------------------------------------------


package n;

import doom.IDoomGameNetworking;
import doom.doomcom_t;

public class DummyNetworkHandler implements IDoomGameNetworking{

    @Override
    public void NetUpdate() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void TryRunTics() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public doomcom_t getDoomCom() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void setDoomCom(doomcom_t doomcom) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public int getTicdup() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void setTicdup(int ticdup) {
        // TODO Auto-generated method stub
        
    }

}

package n;

import static data.Limits.MAXNETNODES;
import static doom.NetConsts.CMD_GET;
import static doom.NetConsts.CMD_SEND;
import static doom.NetConsts.DOOMCOM_ID;
import i.DoomStatusAware;
import i.IDoomSystem;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;

import w.DoomBuffer;
import doom.DoomContext;
import doom.DoomMain;
import doom.DoomStatus;
import doom.doomcom_t;
import doom.doomdata_t;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: BasicNetworkInterface.java,v 1.5 2011/05/26 13:39:06 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: BasicNetworkInterface.java,v $
// Revision 1.5  2011/05/26 13:39:06  velktron
// Now using ICommandLineManager
//
// Revision 1.4  2011/05/18 16:54:31  velktron
// Changed to DoomStatus
//
// Revision 1.3  2011/05/17 16:53:42  velktron
// _D_'s version.
//
// Revision 1.2  2010/12/20 17:15:08  velktron
// Made the renderer more OO -> TextureManager and other changes as well.
//
// Revision 1.1  2010/11/17 23:55:06  velktron
// Kind of playable/controllable.
//
// Revision 1.2  2010/11/11 15:31:28  velktron
// Fixed "warped floor" error.
//
// Revision 1.1  2010/10/22 16:22:43  velktron
// Renderer works stably enough but a ton of bleeding. Started working on netcode.
//
//
// DESCRIPTION:
//
//-----------------------------------------------------------------------------

public class BasicNetworkInterface
        implements DoomSystemNetworking, DoomStatusAware {


  public static final String rcsid = "$Id: BasicNetworkInterface.java,v 1.5 2011/05/26 13:39:06 velktron Exp $";

  ////////////// STATUS ///////////
  
  IDoomSystem I;
  protected DoomMain DM;
  
  public BasicNetworkInterface(DoomContext DC){
      this.DM=DC.DM;
      //this.myargv=DM.myargv;
      //this.myargc=DM.myargc;
      sendData=new doomdata_t();
      recvData=new doomdata_t();
      // We can do that since the buffer is reused.
      // Note: this will effectively tie doomdata and the datapacket.
      recvPacket=new DatagramPacket(recvData.cached(),recvData.cached().length);
      sendPacket=new DatagramPacket(sendData.cached(),sendData.cached().length);
      
      
  }
  
  // Bind it to the ones inside DN and DM;  
  //doomdata_t netbuffer;
  doomcom_t doomcom;
  
  
  // For some odd reason...
  
  /** Changes endianness of a number */
  
  public static int ntohl(int x) {      
   return       ((((x & 0x000000ff) << 24) | 
                               ((x & 0x0000ff00) <<  8) | 
                               ((x & 0x00ff0000) >>>  8) | 
                               ((x & 0xff000000) >>> 24)));
      }

  public static short ntohs(short x) {
      return (short) (((x & 0x00ff) << 8) | ((x & 0xff00) >>> 8));
      }
        
  public static int htonl(int x) {
      return ntohl(x);
      }
  
  public static short htons(short x){
      return ntohs(x);
  }

  //void    NetSend ();
  //boolean NetListen ();


  //
  // NETWORKING
  //

  // Maes: come on, we all know it's 666.
  int DOOMPORT =  666;//(IPPORT_USERRESERVED +0x1d );
  
  //_D_: for testing purposes. If testing on the same machine, we can't have two UDP servers on the same port
  int RECVPORT = DOOMPORT;
  int SENDPORT = DOOMPORT;

  //DatagramSocket         sendsocket;
  DatagramSocket         insocket;

    
  // MAES: closest java equivalent
  DatagramSocket /*InetAddress*/ sendaddress[]=new DatagramSocket/*InetAddress*/[MAXNETNODES];

  
  interface NetFunction {
      public void invoke();
  }
  

  // To use inside packetsend. Declare once and reuse to save on heap costs.
  private doomdata_t  sendData;
  private doomdata_t  recvData;
  
  // We also reuse always the same DatagramPacket, "peged" to sw's byte buffer.
  private DatagramPacket recvPacket;
  private DatagramPacket sendPacket;
  
  public void sendSocketPacket(DatagramSocket ds, DatagramPacket dp) throws IOException {
      ds.send(dp);
  }

  public PacketSend packetSend = new PacketSend();

  public class PacketSend implements NetFunction {

      @Override
      public void invoke() {
          int     c;

          doomdata_t netbuffer = DM.netbuffer;

          // byte swap: so this is transferred as little endian? Ugh
          /*sendData.checksum = htonl(netbuffer.checksum);
          sendData.player = netbuffer.player;
          sendData.retransmitfrom = netbuffer.retransmitfrom;
          sendData.starttic = netbuffer.starttic;
          sendData.numtics = netbuffer.numtics;
          for (c=0 ; c< netbuffer.numtics ; c++)
          {
              sendData.cmds[c].forwardmove = netbuffer.cmds[c].forwardmove;
              sendData.cmds[c].sidemove = netbuffer.cmds[c].sidemove;
              sendData.cmds[c].angleturn = htons(netbuffer.cmds[c].angleturn);
              sendData.cmds[c].consistancy = htons(netbuffer.cmds[c].consistancy);
              sendData.cmds[c].chatchar = netbuffer.cmds[c].chatchar;
              sendData.cmds[c].buttons = netbuffer.cmds[c].buttons;
          }
*/
          //printf ("sending %i\n",gametic);      
          
          sendData.copyFrom(netbuffer);
          // MAES: This will force the buffer to be refreshed.
          byte[] bytes = sendData.pack();

          /*System.out.print("SEND >> Thisplayer: "+DM.consoleplayer+" numtics: "+sendData.numtics+" consistency: ");
          for (doom.ticcmd_t t: sendData.cmds)
              System.out.print(t.consistancy+",");
          System.out.println();*/

          // The socket already contains the address it needs,
          // and the packet's buffer is already modified. Send away.
          sendPacket.setData(bytes, 0, doomcom.datalength);
          DatagramSocket sendsocket;
          try {
              sendsocket = sendaddress[doomcom.remotenode];
              sendPacket.setSocketAddress(sendsocket.getRemoteSocketAddress());
              sendSocketPacket(sendsocket, sendPacket);
          } catch (Exception e) {
              e.printStackTrace();
              I.Error ("SendPacket error: %s",e.getMessage());
          }

          //  if (c == -1)
          //      I_Error ("SendPacket error: %s",strerror(errno));
      }

  }


  public void socketGetPacket(DatagramSocket ds, DatagramPacket dp) throws IOException {
      ds.receive(dp);
  }
  
  // Used inside PacketGet
  private boolean first=true;

  public PacketGet packetGet = new PacketGet();
  public class PacketGet implements NetFunction {

      @Override
      public void invoke() {
          int         i;
          int         c;

          // Receive back into swp.
          try {
              //recvPacket.setSocketAddress(insocket.getLocalSocketAddress());
              socketGetPacket(insocket, recvPacket);
          } 
          catch (SocketTimeoutException e) {
              doomcom.remotenode = -1;       // no packet
              return;
          }
          catch (Exception e)
          { if (e.getClass()!=java.nio.channels.IllegalBlockingModeException.class){
              I.Error ("GetPacket: %s",e.getStackTrace());
          }
          }

          recvData.unpack(recvPacket.getData());
          InetAddress fromaddress = recvPacket.getAddress();

          /*System.out.print("RECV << Thisplayer: "+DM.consoleplayer+" numtics: "+recvData.numtics+" consistency: ");
          for (doom.ticcmd_t t: recvData.cmds)
              System.out.print(t.consistancy+",");
          System.out.println();*/
          
          {
              //static int first=1;
              if (first){
                  sb.setLength(0);
                  sb.append("("+DM.consoleplayer+") PacketRECV len=");
                  sb.append(recvPacket.getLength());
                  sb.append(":p=[0x");
                  sb.append(Integer.toHexString(recvData.checksum));
                  sb.append(" 0x");
                  sb.append(DoomBuffer.getBEInt(recvData.retransmitfrom,recvData.starttic,recvData.player,recvData.numtics));
                  sb.append("numtics: "+recvData.numtics);
                  System.out.println(sb.toString());
                  first = false;
              }
          }

          // find remote node number
          for (i=0 ; i<doomcom.numnodes ; i++) {
              if (sendaddress[i] != null) {
                  if (fromaddress.equals(sendaddress[i].getInetAddress()))
                      break;
              }
          }

          if (i == doomcom.numnodes)
          {
              // packet is not from one of the players (new game broadcast)
              doomcom.remotenode = -1;       // no packet
              return;
          }

          doomcom.remotenode = (short) i;            // good packet from a game player
          doomcom.datalength = (short) recvPacket.getLength();

          //_D_: temporary hack to test two player on single machine
          //doomcom.remotenode = (short)(RECVPORT-DOOMPORT);
          

          
          // byte swap
          /*doomdata_t netbuffer = DM.netbuffer;
          netbuffer.checksum = ntohl(recvData.checksum);
          netbuffer.player = recvData.player;
          netbuffer.retransmitfrom = recvData.retransmitfrom;
          netbuffer.starttic = recvData.starttic;
          netbuffer.numtics = recvData.numtics;

          for (c=0 ; c< netbuffer.numtics ; c++)
          {
              netbuffer.cmds[c].forwardmove = recvData.cmds[c].forwardmove;
              netbuffer.cmds[c].sidemove = recvData.cmds[c].sidemove;
              netbuffer.cmds[c].angleturn = ntohs(recvData.cmds[c].angleturn);
              netbuffer.cmds[c].consistancy = ntohs(recvData.cmds[c].consistancy);
              netbuffer.cmds[c].chatchar = recvData.cmds[c].chatchar;
              netbuffer.cmds[c].buttons = recvData.cmds[c].buttons;
          } */
          DM.netbuffer.copyFrom(recvData);

      }

  };

  // Maes: oh great. More function pointer "fun".
  NetFunction netget = packetGet;
  NetFunction netsend = packetSend;


  //
  // I_InitNetwork
  //
    
  @Override
  public void InitNetwork() {
      boolean     trueval = true;
      int         i;
      int         p;
      //struct hostent* hostentry;  // host information entry

      doomcom = new doomcom_t();
      //netbuffer = new doomdata_t();
      DM.setDoomCom(doomcom);
      //DM.netbuffer = netbuffer;

      // set up for network
      i = DM.CM.CheckParm ("-dup");
      if ((i!=0) && i< DM.CM.getArgc()-1)
      {
          doomcom.ticdup = (short) (DM.CM.getArgv(i+1).charAt(0)-'0');
          if (doomcom.ticdup < 1)
              doomcom.ticdup = 1;
          if (doomcom.ticdup > 9)
              doomcom.ticdup = 9;
      }
      else
          doomcom. ticdup = 1;

      if (DM.CM.CheckParm ("-extratic")!=0)
          doomcom. extratics = 1;
      else
          doomcom. extratics = 0;

      p = DM.CM.CheckParm ("-port");
      if ((p!=0) && (p<DM.CM.getArgc()-1))
      {
          DOOMPORT = Integer.parseInt(DM.CM.getArgv(p+1));
          System.out.println ("using alternate port "+DOOMPORT);
      }

      // parse network game options,
      //  -net <consoleplayer> <host> <host> ...
      i = DM.CM.CheckParm ("-net");
      if (i==0)
      {
          // single player game
          DM.netgame = false;
          doomcom.id = DOOMCOM_ID;
          doomcom.numplayers = doomcom.numnodes = 1;
          doomcom.deathmatch = 0; // false
          doomcom.consoleplayer = 0;
          return;
      }

      DM.netgame = true;

      // parse player number and host list
      doomcom.consoleplayer = (short) (DM.CM.getArgv(i+1).charAt(0)-'1');
      
      RECVPORT = SENDPORT = DOOMPORT;
      if (doomcom.consoleplayer == 0)
          SENDPORT++;
      else
          RECVPORT++;

      doomcom.numnodes = 1;  // this node for sure

      i++;
      while (++i < DM.CM.getArgc() && DM.CM.getArgv(i).charAt(0) != '-')
      {
          try {
          InetAddress addr = InetAddress.getByName(DM.CM.getArgv(i));
          DatagramSocket ds = new DatagramSocket(null);
          ds.setReuseAddress(true);
          ds.connect(addr, SENDPORT);

          sendaddress[doomcom.numnodes] = ds;
          }catch (Exception e) {
              e.printStackTrace();
          }
          
          doomcom.numnodes++;
      }

      doomcom.id = DOOMCOM_ID;
      doomcom.numplayers = doomcom.numnodes;

      // build message to receive
      try {
          insocket = new DatagramSocket(null);
          insocket.setReuseAddress(true);
          insocket.setSoTimeout(1);
          insocket.bind(new InetSocketAddress(RECVPORT));
      } catch (SocketException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
      }
  }

    @Override
    public void NetCmd() {
          if (insocket == null) //HACK in case "netgame" is due to "addbot"
              return;

        if (DM.doomcom.command == CMD_SEND)
        {
        netsend.invoke ();
        }
        else if (doomcom.command == CMD_GET)
        {
        netget.invoke ();
        }
        else
        I.Error ("Bad net cmd: %i\n",doomcom.command);

    }

    // Instance StringBuilder
    private StringBuilder sb=new StringBuilder();

    @Override
    public void updateStatus(DoomStatus DC) {
        // TODO Auto-generated method stub
        
    }
    
}

package n;

public interface IDoomNet {
    public void NetUpdate();
}

package f;

/* Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: EndLevel.java,v 1.12 2016/07/04 07:52:26 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: EndLevel.java,v $
// Revision 1.12  2016/07/04 07:52:26  velktron
// GPL license header, and cleanup for files that are not in direct correspondence with original ones.
//
// Revision 1.11  2012/09/24 17:16:23  velktron
// Massive merge between HiColor and HEAD. There's no difference from now on, and development continues on HEAD.
//
// Revision 1.8.2.2  2012/09/24 16:57:43  velktron
// Addressed generics warnings.
//
// Revision 1.8.2.1  2011/11/27 18:18:34  velktron
// Use cacheClear() on deactivation.
//
// Revision 1.8  2011/11/01 19:02:57  velktron
// Using screen number constants
//
// Revision 1.7  2011/10/23 18:11:32  velktron
// Generic compliance for DoomVideoInterface
//
// Revision 1.6  2011/08/23 16:13:53  velktron
// Got rid of Z remnants.
//
// Revision 1.5  2011/07/31 21:49:38  velktron
// Changed endlevel drawer's behavior to be closer to prBoom+'s. Allows using 1994TU.WAD while backwards compatible.
//
// Revision 1.4  2011/06/02 14:56:48  velktron
// imports
//
// Revision 1.3  2011/06/02 14:53:21  velktron
// Moved Endlevel constants to AbstractEndLevel
//
// Revision 1.2  2011/06/02 14:14:28  velktron
// Implemented endlevel unloading of graphics, changed state enum.
//
// Revision 1.1  2011/06/02 14:00:48  velktron
// Moved Endlevel stuff  to f, where it makes more sense.
//
// Revision 1.18  2011/05/31 12:25:14  velktron
// Endlevel -mostly- scaled correctly.
//
// Revision 1.17  2011/05/29 22:15:32  velktron
// Introduced IRandom interface.
//
// Revision 1.16  2011/05/24 17:54:02  velktron
// Defaults tester
//
// Revision 1.15  2011/05/23 17:00:39  velktron
// Got rid of verbosity
//
// Revision 1.14  2011/05/21 16:53:24  velktron
// Adapted to use new gamemode system.
//
// Revision 1.13  2011/05/18 16:58:04  velktron
// Changed to DoomStatus
//
// Revision 1.12  2011/05/17 16:52:19  velktron
// Switched to DoomStatus
//
// Revision 1.11  2011/05/11 14:12:08  velktron
// Interfaced with DoomGame
//
// Revision 1.10  2011/05/10 10:39:18  velktron
// Semi-playable Techdemo v1.3 milestone
//
// Revision 1.9  2011/05/06 14:00:54  velktron
// More of _D_'s changes committed.
//
// Revision 1.8  2011/02/11 00:11:13  velktron
// A MUCH needed update to v1.3.
//
// Revision 1.7  2010/12/20 17:15:08  velktron
// Made the renderer more OO -> TextureManager and other changes as well.
//
// Revision 1.6  2010/11/12 13:37:25  velktron
// Rationalized the LUT system - now it's 100% procedurally generated.
//
// Revision 1.5  2010/09/23 07:31:11  velktron
// fuck
//
// Revision 1.4  2010/09/02 15:56:54  velktron
// Bulk of unified renderer copyediting done.
//
// Some changes like e.g. global separate limits class and instance methods for seg_t and node_t introduced.
//
// Revision 1.3  2010/08/23 14:36:08  velktron
// Menu mostly working, implemented Killough's fast hash-based GetNumForName, although it can probably be finetuned even more.
//
// Revision 1.2  2010/08/13 14:06:36  velktron
// Endlevel screen fully functional!
//
// Revision 1.1  2010/07/06 16:32:38  velktron
// Threw some work in WI, now EndLevel. YEAH THERE'S GONNA BE A SEPARATE EndLevel OBJECT THAT'S HOW PIMP THE PROJECT IS!!!!11!!!
//
// Revision 1.1  2010/06/30 08:58:51  velktron
// Let's see if this stuff will finally commit....
//
//
// Most stuff is still  being worked on. For a good place to start and get an idea of what is being done, I suggest checking out the "testers" package.
//
// Revision 1.1  2010/06/29 11:07:34  velktron
// Release often, release early they say...
//
// Commiting ALL stuff done so far. A lot of stuff is still broken/incomplete, and there's still mixed C code in there. I suggest you load everything up in Eclpise and see what gives from there.
//
// A good place to start is the testers/ directory, where you  can get an idea of how a few of the implemented stuff works.
//
//
// DESCRIPTION:
//	Intermission screens.
//
//-----------------------------------------------------------------------------*/


import static data.Defines.*;
import static data.Limits.*;
import static v.DoomVideoRenderer.*;
import defines.*;
import data.sounds.musicenum_t;
import data.sounds.sfxenum_t;
import doom.DoomMain;
import doom.DoomStatus;
import doom.IDoomGame;
import doom.event_t;
import doom.player_t;
import doom.wbplayerstruct_t;
import doom.wbstartstruct_t;
import m.IRandom;
import rr.*;
import s.IDoomSound;
import st.IDoomStatusBar;
import v.DoomVideoRenderer;
import v.IVideoScale;
import w.IWadLoader;
import w.animenum_t;

/** This class (stuff.c) seems to implement the endlevel screens.
 * 
 * @author Maes
 *
 */

public class EndLevel<T,V> extends AbstractEndLevel {

    ////////////////// STATUS ///////////////////
    private DoomMain<?,?> DS;
    private IDoomGame DG;
    private DoomVideoRenderer<?,?> V;
    private IDoomSound S;
    private IWadLoader W;
    private IDoomStatusBar ST;
    private IRandom RND;
    
    private static int COUNT_KILLS=2;
    private static int COUNT_ITEMS=4;
    private static int COUNT_SECRETS=6;
    private static int COUNT_TIME=8;
    private static int COUNT_DONE=10;
    
    static enum endlevel_state{
    	NoState,
    	StatCount,
    	ShowNextLoc, 
    	JustShutOff
    }
    
  //GLOBAL LOCATIONS
    private static final int WI_TITLEY       =2;
    private static final int WI_SPACINGY         =3;
    
    
//
// GENERAL DATA
//

//
// Locally used stuff.
//
public static final int FB= 0;
private static final boolean RANGECHECKING = true;

// Where to draw some stuff. To be scaled up, so they
// are not final.

public static int SP_STATSX;
public static int SP_STATSY;

public static int SP_TIMEX;
public static int SP_TIMEY;

// States for single-player
protected static int SP_KILLS	=	0;
protected static int SP_ITEMS	=	2;
protected static int SP_SECRET	=	4;
protected static int SP_FRAGS	=	6 ;
protected static int SP_TIME		=	8 ;
protected static int SP_PAR		=	SP_TIME;

protected int SP_PAUSE	=	1;

// in seconds
protected  int SHOWNEXTLOCDELAY	=4;
protected  int SHOWLASTLOCDELAY	=SHOWNEXTLOCDELAY;

// used to accelerate or skip a stage
int		acceleratestage;

// wbs->pnum
int		me;

 // specifies current state )
endlevel_state	state;

// contains information passed into intermission
public wbstartstruct_t	wbs;

wbplayerstruct_t[] plrs;  // wbs->plyr[]

// used for general timing
int 		cnt;  

// used for timing of background animation
int 		bcnt;

// signals to refresh everything for one frame
int 		firstrefresh; 

int[]		cnt_kills=new int[MAXPLAYERS];
int[]		cnt_items=new int[MAXPLAYERS];
int[]		cnt_secret=new int[MAXPLAYERS];
int		cnt_time;
int		cnt_par;
int		cnt_pause;

// # of commercial levels
int		NUMCMAPS; 


//
//	GRAPHICS
//

// background (map of levels).
patch_t		bg;

// You Are Here graphic
patch_t[]		yah=new patch_t[2]; 

// splat
patch_t		splat;

/** %, : graphics */
patch_t		percent,colon;

/** 0-9 graphic */
patch_t[]		num=new patch_t[10];

/** minus sign */
 patch_t	wiminus;

// "Finished!" graphics
 patch_t		finished;

// "Entering" graphic
 patch_t		entering; 

// "secret"
 patch_t		sp_secret;

 /** "Kills", "Scrt", "Items", "Frags" */
 patch_t		kills,	secret,items,frags;

/** Time sucks. */
 patch_t		time,	par,sucks;

/** "killers", "victims" */
 patch_t		killers,victims; 

/** "Total", your face, your dead face */
 patch_t		total,	star, bstar;

/** "red P[1..MAXPLAYERS]"*/
 patch_t[]		p=new patch_t[MAXPLAYERS];

/** "gray P[1..MAXPLAYERS]" */
 patch_t[] bp=new patch_t[MAXPLAYERS];

 /** Name graphics of each level (centered) */
 patch_t[]	lnames;

//
// CODE
//

// slam background
// UNUSED  unsigned char *background=0;


public EndLevel(DoomStatus<T,V> DC) {
    this.updateStatus(DC);
   
    // _D_: commented this, otherwise something didn't work
    //this.Start(DS.wminfo);
}

protected void slamBackground()
{
    //    memcpy(screens[0], screens[1], SCREENWIDTH * SCREENHEIGHT);
    // Remember, the second arg is the source!
    System.arraycopy(V.getScreen(SCREEN_BG), 0 ,V.getScreen(SCREEN_FG),0, SCREENWIDTH * SCREENHEIGHT);
    V.MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
}

// The ticker is used to detect keys
//  because of timing issues in netgames.
public boolean Responder(event_t ev)
{
    return false;
}


/** Draws "<Levelname> Finished!" */	
protected void drawLF()
{
    int y = WI_TITLEY;

    // draw <LevelName> 
    V.DrawScaledPatch((320 - lnames[wbs.last].width)/2,
        y, FB,vs, lnames[wbs.last]);

    // draw "Finished!"
    y += (5*lnames[wbs.last].height)/4;
    
    V.DrawScaledPatch((320 - finished.width)/2,
        y, FB,vs, finished);
}



/** Draws "Entering <LevelName>" */
protected void drawEL()
{
    int y = WI_TITLEY; // This is in 320 x 200 coords!

    // draw "Entering"
    V.DrawScaledPatch((320 - entering.width)/2, y, FB,vs, entering);
    
    // HACK: if lnames[wbs.next] DOES have a defined nonzero topoffset, use it.
    // implicitly in DrawScaledPatch, and trump the normal behavior.
    // FIXME: this is only useful in a handful of prBoom+ maps, which use
    // a modified endlevel screen. The reason it works there is the behavior of the 
    // unified patch drawing function, which is approximated with this hack.
    
    
    	if (lnames[wbs.next].topoffset==0) 
    	y += (5*lnames[wbs.next].height)/4;
    // draw level.
        
    V.DrawScaledPatch((320 - lnames[wbs.next].width)/2,
        y, FB,vs, lnames[wbs.next]);
 
}

/** For whatever fucked-up reason, it expects c to be an array of patches, 
 *  and may choose to draw from alternative ones...which however are never loaded,
 *  or are supposed to be "next" in memory or whatever. I kept this behavior, however 
 *  in Java it will NOT work as intended, if ever.
 * 
 * @param n
 * @param c
 */

protected void
drawOnLnode
( int		n,
  patch_t[]	c )
{

    int		i;
    int		left;
    int		top;
    int		right;
    int		bottom;
    boolean	fits = false;

    i = 0;
    do
    {
	left = lnodes[wbs.epsd][n].x - c[i].leftoffset;
	top = lnodes[wbs.epsd][n].y - c[i].topoffset;
	right = left + c[i].width;
	bottom = top + c[i].height;

	if (left >= 0
	    && right < SCREENWIDTH
	    && top >= 0
	    && bottom < SCREENHEIGHT)
	{
	    fits = true;
	}
	else
	{
	    i++;
	}
    } while (!fits && i!=2);

    if (fits && i<2)
    {
	//V.DrawPatch(lnodes[wbs.epsd][n].x, lnodes[wbs.epsd][n].y,
	//	    FB, c[i]);
        V./*DrawPatchDirect*/DrawScaledPatch(lnodes[wbs.epsd][n].x, lnodes[wbs.epsd][n].y,
            FB, vs,c[i]);
    }
    else
    {
	// DEBUG
	System.out.println("Could not place patch on level "+ n+1); 
    }
}



protected void initAnimatedBack()
{
    int		i;
    anim_t	a;

    if (DS.isCommercial())
	return;

    if (wbs.epsd > 2)
	return;

    for (i=0;i<NUMANIMS[wbs.epsd];i++)
    {
	a = anims[wbs.epsd][i];

	// init variables
	a.ctr = -1;

	// specify the next time to draw it
	if (a.type == animenum_t.ANIM_ALWAYS)
	    a.nexttic = bcnt + 1 + (RND.M_Random()%a.period);
	else if (a.type == animenum_t.ANIM_RANDOM)
	    a.nexttic = bcnt + 1 + a.data2+(RND.M_Random()%a.data1);
	else if (a.type == animenum_t.ANIM_LEVEL)
	    a.nexttic = bcnt + 1;
    }

}

protected void updateAnimatedBack()
{
    int		i;
    anim_t	a;

    if (DS.isCommercial())
	return;

    if (wbs.epsd > 2)
	return;

    int aaptr=wbs.epsd;
    
    for (i=0;i<NUMANIMS[wbs.epsd];i++)
    {
	a = anims[aaptr][i];
	
	if (bcnt == a.nexttic)
	{
	    switch (a.type)
	    {
	      case ANIM_ALWAYS:
		if (++anims[aaptr][i].ctr >= a.nanims) a.ctr = 0;
		a.nexttic = bcnt + a.period;
		break;

	      case ANIM_RANDOM:
		a.ctr++;
		if (a.ctr == a.nanims)
		{
		    a.ctr = -1;
		    a.nexttic = bcnt+a.data2+(RND.M_Random()%a.data1);
		}
		else a.nexttic = bcnt + a.period;
		break;
		
	      case ANIM_LEVEL:
		// gawd-awful hack for level anims
		if (!(state == endlevel_state.StatCount && i == 7)
		    && wbs.next == a.data1)
		{
		    a.ctr++;
		    if (a.ctr == a.nanims) a.ctr--;
		    a.nexttic = bcnt + a.period;
		}
		break;
	    }
	}

    }

}

protected void drawAnimatedBack()
{
    int			i;
    anim_t		a;

    if (DS.isCommercial())
	return;

    if (wbs.epsd > 2)
	return;

    for (i=0 ; i<NUMANIMS[wbs.epsd] ; i++)
    {
	a = anims[wbs.epsd][i];

	if (a.ctr >= 0)
	    V.DrawScaledPatch(a.loc.x, a.loc.y, FB,vs, a.p[a.ctr]);
    }

}

/**
 * Draws a number.
 * If digits > 0, then use that many digits minimum,
 *  otherwise only use as many as necessary.
 * Returns new x position.
 */

protected int
drawNum
( int		x,
  int		y,
  int		n,
  int		digits )
{

    int		fontwidth = num[0].width;
    boolean		neg;
    int		temp;

    if (digits < 0)
    {
	if (n==0)
	{
	    // make variable-length zeros 1 digit long
	    digits = 1;
	}
	else
	{
	    // figure out # of digits in #
	    digits = 0;
	    temp = n;

	    while (temp!=0)
	    {
		temp /= 10;
		digits++;
	    }
	}
    }

    neg = (n < 0);
    if (neg)
	n = -n;

    // if non-number, do not draw it
    if (n == 1994)
	return 0;

    // draw the new number
    while ((digits--)!=0)
    {
	x -= fontwidth*BEST_X_SCALE;
	V.DrawScaledPatch(x, y, V_NOSCALESTART|FB,vs, num[ n % 10 ]);
	n /= 10;
    }

    // draw a minus sign if necessary
    if (neg)
	V.DrawScaledPatch(x-=8*BEST_X_SCALE, y, V_NOSCALESTART|FB,vs, wiminus);

    return x;

}

protected 

void
drawPercent
( int		x,
  int		y,
  int		p )
{
    if (p < 0)
	return;

    V.DrawScaledPatch(x, y, V_NOSCALESTART|FB,vs, percent);
    drawNum(x, y, p, -1);
}



//
// Display level completion time and par,
//  or "sucks" message if overflow.
//
protected void drawTime
( int		x,
  int		y,
  int		t )
{

    int		div;
    int		n;

    if (t<0)
	return;

    if (t <= 61*59)
    {
	div = 1;

	do
	{
	    n = (t / div) % 60;
	    x = drawNum(x, y, n, 2) - colon.width*BEST_X_SCALE;
	    div *= 60;

	    // draw
	    if ((div==60) || (t / div)>0)
		V.DrawScaledPatch(x, y, V_NOSCALESTART|FB, vs,colon);
	    
	} while ((t / div)>0);
    }
    else
    {
	// "sucks"
	V.DrawScaledPatch(x - sucks.width*BEST_X_SCALE, y, V_NOSCALESTART|FB, vs,sucks); 
    }
}


protected void End()
{
	state=endlevel_state.JustShutOff;
	V.clearCaches();
    unloadData();
}

protected void unloadData()
{
  int   i;
  int   j;

  W.UnlockLumpNum(wiminus); wiminus=null;

  for (i=0 ; i<10 ; i++) {
    W.UnlockLumpNum(num[i]); num[i]=null;
  	}
    
  if (DS.isCommercial())
    {
      for (i=0 ; i<NUMCMAPS ; i++){
        W.UnlockLumpNum(lnames[i]); lnames[i]=null;
      }
    }
  else
    {
      W.UnlockLumpNum(yah[0]); yah[0]=null;
      W.UnlockLumpNum(yah[1]); yah[1]=null;

      W.UnlockLumpNum(splat); splat=null;

      for (i=0 ; i<NUMMAPS ; i++) {
        W.UnlockLumpNum(lnames[i]); lnames[i]=null;
  
      }
      if (wbs.epsd < 3)
        {
          for (j=0;j<NUMANIMS[wbs.epsd];j++)
            {
              if (wbs.epsd != 1 || j != 8)
                for (i=0;i<anims[wbs.epsd][j].nanims;i++){
                  W.UnlockLumpNum(anims[wbs.epsd][j].p[i]);
                  anims[wbs.epsd][j].p[i]=null;
                }
            }
        }
    }
  W.UnlockLumpNum(percent); percent=null;
  W.UnlockLumpNum(colon); colon=null;
  W.UnlockLumpNum(finished); finished=null;
  W.UnlockLumpNum(entering); entering=null;
  W.UnlockLumpNum(kills); kills=null;
  W.UnlockLumpNum(secret); secret=null;
  W.UnlockLumpNum(sp_secret); sp_secret=null;
  W.UnlockLumpNum(items); items=null;
  W.UnlockLumpNum(frags); frags=null;
  W.UnlockLumpNum(time); time=null;
  W.UnlockLumpNum(sucks); sucks=null;
  W.UnlockLumpNum(par); par=null;
  W.UnlockLumpNum(victims); victims=null;
  W.UnlockLumpNum(killers); killers=null;
  W.UnlockLumpNum(total); total=null;
  for (i=0 ; i<MAXPLAYERS ; i++) {
    W.UnlockLumpNum(p[i]);
    W.UnlockLumpNum(bp[i]);
    p[i]=null;
    bp[i]=null;
  }
}


protected void initNoState()
{
    state = endlevel_state.NoState;
    acceleratestage = 0;
    cnt = 10;
}

protected void updateNoState() {

    updateAnimatedBack();

    if (--cnt==00)
    {
	End();
	DG.WorldDone();
    }

}

boolean		snl_pointeron = false;


protected void initShowNextLoc()
{
    state = endlevel_state.ShowNextLoc;
    acceleratestage = 0;
    cnt = SHOWNEXTLOCDELAY * TICRATE;

    initAnimatedBack();
}

protected void updateShowNextLoc()
{
    updateAnimatedBack();

    if ((--cnt==0) || (acceleratestage!=0))
	initNoState();
    else
	snl_pointeron = (cnt & 31) < 20;
}

protected void drawShowNextLoc()
{

    int		i;
    int		last;

    slamBackground();

    // draw animated background
    drawAnimatedBack(); 

    if ( !DS.isCommercial())
    {
  	if (wbs.epsd > 2)
	{
	    drawEL();
	    return;
	}
	
	last = (wbs.last == 8) ? wbs.next - 1 : wbs.last;

	// draw a splat on taken cities.
	for (i=0 ; i<=last ; i++)
	    drawOnLnode(i, new patch_t[]{splat});

	// splat the secret level?
	if (wbs.didsecret)
	    drawOnLnode(8, new patch_t[]{splat});

	// draw flashing ptr
	if (snl_pointeron)
	    drawOnLnode(wbs.next, yah); 
    }

    // draws which level you are entering..
    if ( (!DS.isCommercial())
	 || wbs.next != 30)
	drawEL();  

}

protected void drawNoState()
{
    snl_pointeron = true;
    drawShowNextLoc();
}

protected int fragSum(int playernum)
{
    int		i;
    int		frags = 0;
    
    for (i=0 ; i<MAXPLAYERS ; i++)
    {
	if (DS.playeringame[i]
	    && i!=playernum)
	{
	    frags += plrs[playernum].frags[i];
	}
    }

	
    // JDC hack - negative frags.
    frags -= plrs[playernum].frags[playernum];
    // UNUSED if (frags < 0)
    // 	frags = 0;

    return frags;
}



int		dm_state;
int[][]		dm_frags=new int[MAXPLAYERS][MAXPLAYERS];
int	[]	dm_totals=new int[MAXPLAYERS];



protected void initDeathmatchStats()
{

    int		i;
    int		j;

    state = endlevel_state.StatCount;
    acceleratestage = 0;
    dm_state = 1;

    cnt_pause = TICRATE;

    for (i=0 ; i<MAXPLAYERS ; i++)
    {
	if (DS.playeringame[i])
	{
	    for (j=0 ; j<MAXPLAYERS ; j++)
		if (DS.playeringame[j])
		    dm_frags[i][j] = 0;

	    dm_totals[i] = 0;
	}
    }
    
    initAnimatedBack();
}



protected void updateDeathmatchStats()
{

    int		i;
    int		j;
    
    boolean	stillticking;

    updateAnimatedBack();

    if ((acceleratestage!=0) && (dm_state != 4))
    {
	acceleratestage = 0;

	for (i=0 ; i<MAXPLAYERS ; i++)
	{
	    if (DS.playeringame[i])
	    {
		for (j=0 ; j<MAXPLAYERS ; j++)
		    if (DS.playeringame[j])
			dm_frags[i][j] = plrs[i].frags[j];

		dm_totals[i] = fragSum(i);
	    }
	}
	

	S.StartSound(null, sfxenum_t.sfx_barexp);
	dm_state = 4;
    }

    
    if (dm_state == 2)
    {
	if ((bcnt&3)==0)
	     S.StartSound(null, sfxenum_t.sfx_pistol);
	
	stillticking = false;

	for (i=0 ; i<MAXPLAYERS ; i++)
	{
	    if (DS.playeringame[i])
	    {
		for (j=0 ; j<MAXPLAYERS ; j++)
		{
		    if (DS.playeringame[j]
			&& dm_frags[i][j] != plrs[i].frags[j])
		    {
			if (plrs[i].frags[j] < 0)
			    dm_frags[i][j]--;
			else
			    dm_frags[i][j]++;

			if (dm_frags[i][j] > 99)
			    dm_frags[i][j] = 99;

			if (dm_frags[i][j] < -99)
			    dm_frags[i][j] = -99;
			
			stillticking = true;
		    }
		}
		dm_totals[i] = fragSum(i);

		if (dm_totals[i] > 99)
		    dm_totals[i] = 99;
		
		if (dm_totals[i] < -99)
		    dm_totals[i] = -99;
	    }
	    
	}
	if (!stillticking)
	{
	    S.StartSound(null,sfxenum_t.sfx_barexp);
	    dm_state++;
	}

    }
    else if (dm_state == 4)
    {
	if (acceleratestage!=0)
	{
	    S.StartSound(null, sfxenum_t.sfx_slop);

	    if ( DS.isCommercial())
		initNoState();
	    else
		initShowNextLoc();
	}
    }
    else if ((dm_state & 1)!=0)
    {
	if (--cnt_pause==0)
	{
	    dm_state++;
	    cnt_pause = TICRATE;
	}
    }
}



protected void drawDeathmatchStats()
{

    int		i;
    int		j;
    int		x;
    int		y;
    int		w;
    
    int		lh = WI_SPACINGY; // line height

    slamBackground();
    
    // draw animated background
    drawAnimatedBack(); 
    drawLF();

    // draw stat titles (top line)
    V.DrawPatch(DM_TOTALSX-total.width/2,
		DM_MATRIXY-WI_SPACINGY+10,
		FB,
		total);
    
    V.DrawPatch(DM_KILLERSX, DM_KILLERSY, FB, killers);
    V.DrawPatch(DM_VICTIMSX, DM_VICTIMSY, FB, victims);

    // draw P?
    x = DM_MATRIXX + DM_SPACINGX;
    y = DM_MATRIXY;

    for (i=0 ; i<MAXPLAYERS ; i++)
    {
	if (DS.playeringame[i])
	{
	    V.DrawPatch(x-p[i].width/2,
			DM_MATRIXY - WI_SPACINGY,
			FB,
			p[i]);
	    
	    V.DrawPatch(DM_MATRIXX-p[i].width/2,
			y,
			FB,
			p[i]);

	    if (i == me)
	    {
		V.DrawPatch(x-p[i].width/2,
			    DM_MATRIXY - WI_SPACINGY,
			    FB,
			    bstar);

		V.DrawPatch(DM_MATRIXX-p[i].width/2,
			    y,
			    FB,
			    star);
	    }
	}
	else
	{
	    // V_DrawPatch(x-SHORT(bp[i].width)/2,
	    //   DM_MATRIXY - WI_SPACINGY, FB, bp[i]);
	    // V_DrawPatch(DM_MATRIXX-SHORT(bp[i].width)/2,
	    //   y, FB, bp[i]);
	}
	x += DM_SPACINGX;
	y += WI_SPACINGY;
    }

    // draw stats
    y = DM_MATRIXY+10;
    w = num[0].width;

    for (i=0 ; i<MAXPLAYERS ; i++)
    {
	x = DM_MATRIXX + DM_SPACINGX;

	if (DS.playeringame[i])
	{
	    for (j=0 ; j<MAXPLAYERS ; j++)
	    {
		if (DS.playeringame[j])
		    drawNum(x+w, y, dm_frags[i][j], 2);

		x += DM_SPACINGX;
	    }
	    drawNum(DM_TOTALSX+w, y, dm_totals[i], 2);
	}
	y += WI_SPACINGY;
    }
}

 int[]	cnt_frags=new int[MAXPLAYERS];
 int	dofrags;
 int	ng_state;

 protected void initNetgameStats()
{

    int i;

    state = endlevel_state.StatCount;
    acceleratestage = 0;
    ng_state = 1;

    cnt_pause = TICRATE;

    for (i=0 ; i<MAXPLAYERS ; i++)
    {
	if (!DS.playeringame[i])
	    continue;

	cnt_kills[i] = cnt_items[i] = cnt_secret[i] = cnt_frags[i] = 0;

	dofrags += fragSum(i);
    }

    dofrags = ~~dofrags;

    initAnimatedBack();
}



protected void updateNetgameStats()
{

    int		i;
    int		fsum;
    
    boolean	stillticking;

    updateAnimatedBack();

    if (acceleratestage!=0 && ng_state != 10)
    {
	acceleratestage = 0;

	for (i=0 ; i<MAXPLAYERS ; i++)
	{
	    if (!DS.playeringame[i])
		continue;

	    cnt_kills[i] = (plrs[i].skills * 100) / wbs.maxkills;
	    cnt_items[i] = (plrs[i].sitems * 100) / wbs.maxitems;
	    cnt_secret[i] = (plrs[i].ssecret * 100) / wbs.maxsecret;

	    if (dofrags!=0)
		cnt_frags[i] = fragSum(i);
	}
	S.StartSound(null, sfxenum_t.sfx_barexp);
	ng_state = 10;
    }

    if (ng_state == 2)
    {
	if ((bcnt&3)==0)
	    S.StartSound(null,  sfxenum_t.sfx_pistol);

	stillticking = false;

	for (i=0 ; i<MAXPLAYERS ; i++)
	{
	    if (!DS.playeringame[i])
		continue;

	    cnt_kills[i] += 2;

	    if (cnt_kills[i] >= (plrs[i].skills * 100) / wbs.maxkills)
		cnt_kills[i] = (plrs[i].skills * 100) / wbs.maxkills;
	    else
		stillticking = true;
	}
	
	if (!stillticking)
	{
	    S.StartSound(null,  sfxenum_t.sfx_barexp);
	    ng_state++;
	}
    }
    else if (ng_state == 4)
    {
	if ((bcnt&3)==0)
	   S.StartSound(null,  sfxenum_t.sfx_pistol);

	stillticking = false;

	for (i=0 ; i<MAXPLAYERS ; i++)
	{
	    if (!DS.playeringame[i])
		continue;

	    cnt_items[i] += 2;
	    if (cnt_items[i] >= (plrs[i].sitems * 100) / wbs.maxitems)
		cnt_items[i] = (plrs[i].sitems * 100) / wbs.maxitems;
	    else
		stillticking = true;
	}
	if (!stillticking)
	{
	   S.StartSound(null,  sfxenum_t.sfx_barexp);
	    ng_state++;
	}
    }
    else if (ng_state == 6)
    {
	if ((bcnt&3)==0)
	   S.StartSound(null,  sfxenum_t.sfx_pistol);

	stillticking = false;

	for (i=0 ; i<MAXPLAYERS ; i++)
	{
	    if (!DS.playeringame[i])
		continue;

	    cnt_secret[i] += 2;

	    if (cnt_secret[i] >= (plrs[i].ssecret * 100) / wbs.maxsecret)
		cnt_secret[i] = (plrs[i].ssecret * 100) / wbs.maxsecret;
	    else
		stillticking = true;
	}
	
	if (!stillticking)
	{
	    S.StartSound(null, sfxenum_t.sfx_barexp);
	    ng_state += 1 + 2*~dofrags;
	}
    }
    else if (ng_state == 8)
    {
	if ((bcnt&3)==0)
	  S.StartSound(null,  sfxenum_t.sfx_pistol);

	stillticking = false;

	for (i=0 ; i<MAXPLAYERS ; i++)
	{
	    if (!DS.playeringame[i])
		continue;

	    cnt_frags[i] += 1;

	    if (cnt_frags[i] >= (fsum = fragSum(i)))
		cnt_frags[i] = fsum;
	    else
		stillticking = true;
	}
	
	if (!stillticking)
	{
	    S.StartSound(null,  sfxenum_t.sfx_pldeth);
	    ng_state++;
	}
    }
    else if (ng_state == 10)
    {
	if (acceleratestage!=0)
	{
	   S.StartSound(null,  sfxenum_t.sfx_sgcock);
	    if ( DS.isCommercial() )
		initNoState();
	    else
		initShowNextLoc();
	}
    }
    else if ((ng_state & 1)!=0)
    {
	if (--cnt_pause==0)
	{
	    ng_state++;
	    cnt_pause = TICRATE;
	}
    }
}

protected void drawNetgameStats()
{
    int		i;
    int		x;
    int		y;
    int		pwidth = percent.width;

    slamBackground();
    
    // draw animated background
    drawAnimatedBack(); 

    drawLF();

    // draw stat titles (top line)
    V.DrawPatch(NG_STATSX()+NG_SPACINGX-kills.width,
		NG_STATSY, FB, kills);

    V.DrawPatch(NG_STATSX()+2*NG_SPACINGX-items.width,
		NG_STATSY, FB, items);

    V.DrawPatch(NG_STATSX()+3*NG_SPACINGX-secret.width,
		NG_STATSY, FB, secret);
    
    if (dofrags!=0)
	V.DrawPatch(NG_STATSX()+4*NG_SPACINGX-frags.width,
		    NG_STATSY, FB, frags);

    // draw stats
    y = NG_STATSY + kills.height;

    for (i=0 ; i<MAXPLAYERS ; i++)
    {
	if (!DS.playeringame[i])
	    continue;

	x = NG_STATSX();
	V.DrawPatch(x-p[i].width, y, FB, p[i]);

	if (i == me)
	    V.DrawPatch(x-p[i].width, y, FB, star);

	x += NG_SPACINGX;
	drawPercent(x-pwidth, y+10, cnt_kills[i]);	x += NG_SPACINGX;
	drawPercent(x-pwidth, y+10, cnt_items[i]);	x += NG_SPACINGX;
	drawPercent(x-pwidth, y+10, cnt_secret[i]);	x += NG_SPACINGX;

	if (dofrags!=0)
	    drawNum(x, y+10, cnt_frags[i], -1);

	y += WI_SPACINGY;
    }

}


 int	sp_state;

 protected void initStats()
{
    state = endlevel_state.StatCount;
    acceleratestage = 0;
    sp_state = 1;
    cnt_kills[0] = cnt_items[0] = cnt_secret[0] = -1;
    cnt_time = cnt_par = -1;
    cnt_pause = TICRATE;

    initAnimatedBack();
}

protected void updateStats()
{

    updateAnimatedBack();
    
    //System.out.println("SP_State "+sp_state);

    if ((acceleratestage !=0) && sp_state != COUNT_DONE)
    {
	acceleratestage = 0;
	cnt_kills[0] = (plrs[me].skills * 100) / wbs.maxkills;
	cnt_items[0] = (plrs[me].sitems * 100) / wbs.maxitems;
	cnt_secret[0] = (plrs[me].ssecret * 100) / wbs.maxsecret;
	cnt_time = plrs[me].stime / TICRATE;
	cnt_par = wbs.partime / TICRATE;
	S.StartSound(null,  sfxenum_t.sfx_barexp);
	sp_state = 10;
    }

    if (sp_state == COUNT_KILLS)
    {
	cnt_kills[0] += 2;

	if ((bcnt&3)==0)
	     S.StartSound(null,  sfxenum_t.sfx_pistol);

	if (cnt_kills[0] >= (plrs[me].skills * 100) / wbs.maxkills)
	{
	    cnt_kills[0] = (plrs[me].skills * 100) / wbs.maxkills;
	    S.StartSound(null, sfxenum_t.sfx_barexp);
	    sp_state++;
	}
    }
    else if (sp_state == COUNT_ITEMS)
    {
	cnt_items[0] += 2;

	if ((bcnt&3)==0)
	     S.StartSound(null, sfxenum_t.sfx_pistol);

	if (cnt_items[0] >= (plrs[me].sitems * 100) / wbs.maxitems)
	{
	    cnt_items[0] = (plrs[me].sitems * 100) / wbs.maxitems;
	     S.StartSound(null, sfxenum_t.sfx_barexp);
	    sp_state++;
	}
    }
    else if (sp_state == COUNT_SECRETS)
    {
	cnt_secret[0] += 2;

	if ((bcnt&3)==0)
	     S.StartSound(null, sfxenum_t.sfx_pistol);

	if (cnt_secret[0] >= (plrs[me].ssecret * 100) / wbs.maxsecret)
	{
	    cnt_secret[0] = (plrs[me].ssecret * 100) / wbs.maxsecret;
	     S.StartSound(null, sfxenum_t.sfx_barexp);
	    sp_state++;
	}
    }

    else if (sp_state == COUNT_TIME)
    {
	if ((bcnt&3)==0)
	    S.StartSound(null, sfxenum_t.sfx_pistol);

	cnt_time += 3;

	if (cnt_time >= plrs[me].stime / TICRATE)
	    cnt_time = plrs[me].stime / TICRATE;

	cnt_par += 3;

	if (cnt_par >= wbs.partime / TICRATE)
	{
	    cnt_par = wbs.partime / TICRATE;

	    if (cnt_time >= plrs[me].stime / TICRATE)
	    {
		 S.StartSound(null, sfxenum_t.sfx_barexp);
		sp_state++;
	    }
	}
    }
    else if (sp_state == COUNT_DONE)
    {
	if (acceleratestage!=0)
	{
	     S.StartSound(null, sfxenum_t.sfx_sgcock);

	    if (DS.isCommercial())
		initNoState();
	    else
		initShowNextLoc();
	}
    }
    // Non-drawing, pausing state. Any odd value introduces a 35 tic pause.
    else if ((sp_state & 1)>0)
    {
	if (--cnt_pause==0)
	{
	    sp_state++;
	    cnt_pause = TICRATE;
	}
    }

}

protected void drawStats()
{
    // line height
    int lh;	

    lh = (3*num[0].height*BEST_Y_SCALE)/2;

    slamBackground();

    // draw animated background
    drawAnimatedBack();
    
    drawLF();

    V.DrawScaledPatch(SP_STATSX, SP_STATSY, V_NOSCALESTART|FB,vs, kills);
    drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cnt_kills[0]);

    V.DrawScaledPatch(SP_STATSX, SP_STATSY+lh, V_NOSCALESTART|FB,vs, items);
    drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+lh, cnt_items[0]);

    V.DrawScaledPatch(SP_STATSX, SP_STATSY+2*lh, V_NOSCALESTART|FB,vs, sp_secret);
    drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY+2*lh, cnt_secret[0]);

    V.DrawScaledPatch(SP_TIMEX, SP_TIMEY, V_NOSCALESTART|FB,vs, time);
    drawTime(SCREENWIDTH/2 - SP_TIMEX, SP_TIMEY, cnt_time);

    if (wbs.epsd < 3)
    {
	V.DrawScaledPatch(SCREENWIDTH/2 + SP_TIMEX, SP_TIMEY, V_NOSCALESTART|FB,vs, par);
	drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cnt_par);
    }

}

protected void checkForAccelerate()
{

    // check for button presses to skip delays
    for (int i=0 ; i<MAXPLAYERS ; i++)
    {
        player_t player = DS.players[i];
	if (DS.playeringame[i])
	{
	    if ((player.cmd.buttons & BT_ATTACK)!=0)
	    {
		if (!player.attackdown)
		    acceleratestage = 1;
		player.attackdown = true;
	    }
	    else
		player.attackdown = false;
	    if ((player.cmd.buttons & BT_USE)!=0)
	    {
		if (!player.usedown)
		    acceleratestage = 1;
		player.usedown = true;
	    }
	    else
		player.usedown = false;
	}
    }
}



/** Updates stuff each tick */
public void Ticker()
{
    // counter for general background animation
    bcnt++;  

    if (bcnt == 1)
    {
	// intermission music
  	if ( DS.isCommercial())
  	
  	    S.ChangeMusic(musicenum_t.mus_dm2int.ordinal(), true);
	else
	    S.ChangeMusic(musicenum_t.mus_inter.ordinal(), true); 
    }

    checkForAccelerate();
//System.out.println("State "+state);
    
    switch (state)
    {
      case StatCount:
	if (DS.deathmatch) updateDeathmatchStats();
	else if (DS.netgame) updateNetgameStats();
	else updateStats();
	break;
	
      case ShowNextLoc:
	updateShowNextLoc();
	break;
	
      case NoState:
	updateNoState();
	 break;
      case JustShutOff:
    	  // We just finished, and graphics have been unloaded.
    	  // If we don't consume a tick in this way, Doom
    	  // will try to draw unloaded graphics.
    	  state=endlevel_state.NoState;
    	  break;
    }

}

protected void loadData()
{
    int		i;
    int		j;
    String	name;
    anim_t	a;

    if (DS.isCommercial())
	name= "INTERPIC";
    else 
	//sprintf(name, "WIMAP%d", wbs.epsd);
        name=("WIMAP"+Integer.toString(wbs.epsd));
    
    // MAES: For Ultimate Doom
    if ( DS.isRetail())
    {
      if (wbs.epsd == 3)
          name= "INTERPIC";
    }

    // background - draw it to screen 1 for quick redraw.
    bg = (patch_t) W.CacheLumpName(name, PU_CACHE,patch_t.class);    
    V.DrawPatchSolidScaled(0, 0, BEST_X_SCALE, BEST_Y_SCALE,1, bg);


    // UNUSED unsigned char *pic = screens[1];
    // if (gamemode == commercial)
    // {
    // darken the background image
    // while (pic != screens[1] + SCREENHEIGHT*SCREENWIDTH)
    // {
    //   *pic = colormaps[256*25 + *pic];
    //   pic++;
    // }
    //}

    if (DS.isCommercial())
    {
	NUMCMAPS = 32;								
//	lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS,
//				       PU_, 0);
	
	lnames=new patch_t[NUMCMAPS];
    String xxx=new String("CWILV%02d");
    //String buffer;
	for (i=0 ; i<NUMCMAPS ; i++)
	{								
	    name=String.format(xxx,i);
	    lnames[i] = (patch_t) W.CacheLumpName(name, PU_STATIC,patch_t.class);
	}					
    }
    else
    {
	lnames = new patch_t[NUMMAPS];
	String xxx=new String("WILV%d%d");

	for (i=0 ; i<NUMMAPS ; i++)
	{
	    name=String.format(xxx,wbs.epsd, i);
	    lnames[i] = (patch_t) W.CacheLumpName(name, PU_STATIC,patch_t.class);
	}

	// you are here
	yah[0] = (patch_t) W.CacheLumpName("WIURH0", PU_STATIC,patch_t.class);

	// you are here (alt.)
	yah[1] = (patch_t) W.CacheLumpName("WIURH1", PU_STATIC,patch_t.class);

	// splat
	splat = (patch_t) W.CacheLumpName("WISPLAT", PU_STATIC,patch_t.class); 
	
	if (wbs.epsd < 3)
	{
	    xxx=new String("WIA%d%02d%02d");
	    //xxx=new PrintfFormat("WIA%d%.2d%.2d");
	    for (j=0;j<NUMANIMS[wbs.epsd];j++)
	    {
		a = anims[wbs.epsd][j];
		for (i=0;i<a.nanims;i++)
		{
		    // MONDO HACK!
		    if (wbs.epsd != 1 || j != 8) 
		    {
			// animations
			name=String.format(xxx,wbs.epsd, j, i);  
			a.p[i] = (patch_t)W.CacheLumpName(name, PU_STATIC,patch_t.class);
		    }
		    else
		    {
			// HACK ALERT!
			a.p[i] = anims[1][4].p[i]; 
		    }
		}
	    }
	}
    }

    // More hacks on minus sign.
    wiminus = (patch_t)W.CacheLumpName("WIMINUS", PU_STATIC,patch_t.class); 

    String xxx=new String("WINUM%d");
    for (i=0;i<10;i++)
    {
	 // numbers 0-9
	name=String.format(xxx,i);     
	num[i] = (patch_t)W.CacheLumpName(name, PU_STATIC,patch_t.class);
    }

    // percent sign
    percent = (patch_t)W.CacheLumpName("WIPCNT", PU_STATIC,patch_t.class);

    // "finished"
    finished = (patch_t)W.CacheLumpName("WIF", PU_STATIC,patch_t.class);

    // "entering"
    entering = (patch_t)W.CacheLumpName("WIENTER", PU_STATIC,patch_t.class);

    // "kills"
    kills = (patch_t)W.CacheLumpName("WIOSTK", PU_STATIC,patch_t.class);   

    // "scrt"
    secret = (patch_t)W.CacheLumpName("WIOSTS", PU_STATIC,patch_t.class);

     // "secret"
    sp_secret =(patch_t)W.CacheLumpName("WISCRT2", PU_STATIC,patch_t.class);

    // Yuck. 
    if (DS.language==Language_t.french)
    {
	// "items"
	if (DS.netgame && !DS.deathmatch)
	    items = (patch_t)W.CacheLumpName("WIOBJ", PU_STATIC,patch_t.class);    
  	else
	    items = (patch_t)W.CacheLumpName("WIOSTI", PU_STATIC,patch_t.class);
    } else
	items = (patch_t)W.CacheLumpName("WIOSTI", PU_STATIC,patch_t.class);

    // "frgs"
    frags = (patch_t)W.CacheLumpName("WIFRGS", PU_STATIC,patch_t.class);    

    // ":"
    colon = (patch_t)W.CacheLumpName("WICOLON", PU_STATIC,patch_t.class); 

    // "time"
    time = (patch_t)W.CacheLumpName("WITIME", PU_STATIC,patch_t.class);  

    // "sucks"
    sucks = (patch_t)W.CacheLumpName("WISUCKS", PU_STATIC,patch_t.class);  

    // "par"
    par = (patch_t)W.CacheLumpName("WIPAR", PU_STATIC,patch_t.class);   

    // "killers" (vertical)
    killers = (patch_t)W.CacheLumpName("WIKILRS", PU_STATIC,patch_t.class);

    // "victims" (horiz)
    victims = (patch_t)W.CacheLumpName("WIVCTMS", PU_STATIC,patch_t.class);

    // "total"
    total = (patch_t)W.CacheLumpName("WIMSTT", PU_STATIC,patch_t.class);   

    // your face
    star = (patch_t)W.CacheLumpName("STFST01", PU_STATIC,patch_t.class);

    // dead face
    bstar = (patch_t)W.CacheLumpName("STFDEAD0", PU_STATIC,patch_t.class);    

    String xx1=new String("STPB%d");
    String xx2=new String("WIBP%d");
    for (i=0 ; i<MAXPLAYERS ; i++)
    {
	// "1,2,3,4"
    name= String.format(xx1,i);
	p[i] = (patch_t)W.CacheLumpName(name, PU_STATIC,patch_t.class);;

	// "1,2,3,4"
	name= String.format(xx2,i+1);
	bp[i] = (patch_t)W.CacheLumpName(name, PU_STATIC,patch_t.class);;
    }

}

/*

public void WI_unloadData()
{
    int		i;
    int		j;

    W.UnlockLumpNum(wiminus, PU_CACHE);

    for (i=0 ; i<10 ; i++)
	W.UnlockLumpNum(num[i], PU_CACHE);
    
    if (gamemode == commercial)
    {
  	for (i=0 ; i<NUMCMAPS ; i++)
	    W.UnlockLumpNum(lnames[i], PU_CACHE);
    }
    else
    {
	W.UnlockLumpNum(yah[0], PU_CACHE);
	W.UnlockLumpNum(yah[1], PU_CACHE);

	W.UnlockLumpNum(splat, PU_CACHE);

	for (i=0 ; i<NUMMAPS ; i++)
	    W.UnlockLumpNum(lnames[i], PU_CACHE);
	
	if (wbs.epsd < 3)
	{
	    for (j=0;j<NUMANIMS[wbs.epsd];j++)
	    {
		if (wbs.epsd != 1 || j != 8)
		    for (i=0;i<anims[wbs.epsd][j].nanims;i++)
			W.UnlockLumpNum(anims[wbs.epsd][j].p[i], PU_CACHE);
	    }
	}
    }
    
    Z_Free(lnames);

    W.UnlockLumpNum(percent, PU_CACHE);
    W.UnlockLumpNum(colon, PU_CACHE);
    W.UnlockLumpNum(finished, PU_CACHE);
    W.UnlockLumpNum(entering, PU_CACHE);
    W.UnlockLumpNum(kills, PU_CACHE);
    W.UnlockLumpNum(secret, PU_CACHE);
    W.UnlockLumpNum(sp_secret, PU_CACHE);
    W.UnlockLumpNum(items, PU_CACHE);
    W.UnlockLumpNum(frags, PU_CACHE);
    W.UnlockLumpNum(time, PU_CACHE);
    W.UnlockLumpNum(sucks, PU_CACHE);
    W.UnlockLumpNum(par, PU_CACHE);

    W.UnlockLumpNum(victims, PU_CACHE);
    W.UnlockLumpNum(killers, PU_CACHE);
    W.UnlockLumpNum(total, PU_CACHE);
    //  W.UnlockLumpNum(star, PU_CACHE);
    //  W.UnlockLumpNum(bstar, PU_CACHE);
    
    for (i=0 ; i<MAXPLAYERS ; i++)
	W.UnlockLumpNum(p[i], PU_CACHE);

    for (i=0 ; i<MAXPLAYERS ; i++)
	W.UnlockLumpNum(bp[i], PU_CACHE);
}
*/


public void Drawer ()
{
    switch (state)
    {
      case StatCount:
	if (DS.deathmatch)
	    drawDeathmatchStats();
	else if (DS.netgame)
	    drawNetgameStats();
	else
	    drawStats();
	break;
	
      case ShowNextLoc:
	drawShowNextLoc();
	break;
	
      case NoState:
	drawNoState();
	break;
    }
}


protected void initVariables(wbstartstruct_t wbstartstruct)
{

    wbs = wbstartstruct.clone();

if (RANGECHECKING){
    if (!DS.isCommercial())
    {
      if ( DS.isRetail())
	RNGCHECK(wbs.epsd, 0, 3);
      else
	RNGCHECK(wbs.epsd, 0, 2);
    }
    else
    {
	RNGCHECK(wbs.last, 0, 8);
	RNGCHECK(wbs.next, 0, 8);
    }
    RNGCHECK(wbs.pnum, 0, MAXPLAYERS);
    RNGCHECK(wbs.pnum, 0, MAXPLAYERS);
}

    acceleratestage = 0;
    cnt = bcnt = 0;
    firstrefresh = 1;
    me = wbs.pnum;
    plrs = wbs.plyr.clone();

    if (wbs.maxkills==0)
	wbs.maxkills = 1;

    if (wbs.maxitems==0)
	wbs.maxitems = 1;

    if (wbs.maxsecret==0)
	wbs.maxsecret = 1;

    // Sanity check for Ultimate.
    if ( !DS.isRetail())
      if (wbs.epsd > 2)
	wbs.epsd -= 3;
}

public void Start(wbstartstruct_t wbstartstruct)
{

    initVariables(wbstartstruct);
    loadData();

    if (DS.deathmatch)
	initDeathmatchStats();
    else if (DS.netgame)
	initNetgameStats();
    else
	initStats();
}


protected int NG_STATSX(){
    return 32 + star.width/2 + 32*~dofrags;
}

protected static boolean RNGCHECK(int what, int min, int max){
    return (what>=min && what <=max)?true:false;
}

@Override
public void updateStatus(DoomStatus DS) {
    this.DG=DS.DG;
    this.DS=DS.DM;
    this.V=DS.V;
    this.W=DS.W;
    this.RND=DS.RND;
    this.S=DS.S;
    this.ST=DS.ST;

    
}


//////////////////////////// VIDEO SCALE STUFF ////////////////////////////////

protected int SCREENWIDTH;
protected int SCREENHEIGHT;
protected IVideoScale vs;
protected int BEST_X_SCALE;
protected int BEST_Y_SCALE;


@Override
public void setVideoScale(IVideoScale vs) {
    this.vs=vs;
}

@Override
public void initScaling() {
    this.SCREENHEIGHT=vs.getScreenHeight();
    this.SCREENWIDTH=vs.getScreenWidth();
    this.BEST_X_SCALE=vs.getScalingX();
    this.BEST_Y_SCALE=vs.getScalingY();
    
    // Pre-scale stuff.
    SP_STATSX       =50*vs.getSafeScaling();
    SP_STATSY      = 50*vs.getSafeScaling();;

    SP_TIMEX      =  16*vs.getSafeScaling();
    SP_TIMEY      =  (SCREENHEIGHT-ST.getHeight());   
}

}
package f;

import static data.Defines.HU_FONTSIZE;
import static data.Defines.HU_FONTSTART;
import static data.Defines.PU_CACHE;
import static data.Defines.PU_LEVEL;
import static data.Defines.FF_FRAMEMASK;
import static data.Limits.MAXPLAYERS;
import static data.info.mobjinfo;
import static data.info.states;
import static doom.englsh.*;
import static utils.C2JUtils.*;
import hu.HU;
import i.DoomStatusAware;

import java.io.IOException;
import java.util.ArrayList;

import rr.ISpriteManager;
import rr.flat_t;
import rr.patch_t;
import rr.spritedef_t;
import rr.spriteframe_t;
import s.IDoomSound;
import utils.C2JUtils;
import v.DoomVideoRenderer;
import v.IVideoScale;
import v.IVideoScaleAware;
import w.IWadLoader;
import data.mobjtype_t;
import data.sounds.musicenum_t;
import data.state_t;
import defines.*;
import data.sounds.sfxenum_t;
import doom.DoomStatus;
import doom.IDoomGame;
import doom.event_t;
import doom.evtype_t;
import doom.gameaction_t;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: Finale.java,v 1.28 2012/09/24 17:16:23 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// DESCRIPTION:
//  Game completion, final screen animation.
//
//-----------------------------------------------------------------------------

public class Finale<T> implements DoomStatusAware, IVideoScaleAware {

	public static final String rcsid = "$Id: Finale.java,v 1.28 2012/09/24 17:16:23 velktron Exp $";

	IDoomGame DG;
	DoomStatus<?,?> DS;
	DoomVideoRenderer<T,?> V;
	IDoomSound S;
	HU HU;
	IWadLoader W;
	ISpriteManager SM;

	int finalestage;

	int finalecount;

	private static int TEXTSPEED = 3;
	private static int TEXTWAIT = 250;

	String[] doom_text = { E1TEXT, E2TEXT, E3TEXT, E4TEXT };

	String[] doom2_text = { C1TEXT, C2TEXT, C3TEXT, C4TEXT, C5TEXT, C6TEXT };

	String[] plut_text = { P1TEXT, P2TEXT, P3TEXT, P4TEXT, P5TEXT, P6TEXT };
	String[] tnt_text = { T1TEXT, T2TEXT, T3TEXT, T4TEXT, T5TEXT, T6TEXT };

	String finaletext;
	String finaleflat;

	/**
	 * F_StartFinale
	 */
	public void StartFinale() {
		DG.setGameAction(gameaction_t.ga_nothing);
		DS.gamestate = gamestate_t.GS_FINALE;
		DS.viewactive = false;
		DS.automapactive = false;
		String[] texts = null;

		// Pick proper text.
		switch (DS.getGameMode()) {
		case commercial:
		case pack_xbla:
			texts = doom2_text;
			break;
		case pack_tnt:
			texts = tnt_text;
			break;
		case pack_plut:
			texts = plut_text;
			break;
		case shareware:
		case registered:
		case retail:
			texts = doom_text;
			break;
		}

		// Okay - IWAD dependend stuff.
		// This has been changed severly, and
		// some stuff might have changed in the process.
		switch (DS.getGameMode()) {

		// DOOM 1 - E1, E3 or E4, but each nine missions
		case shareware:
		case registered:
		case retail: {
			S.ChangeMusic(musicenum_t.mus_victor, true);

			switch (DS.gameepisode) {
			case 1:
				finaleflat = "FLOOR4_8";
				finaletext = texts[0];
				break;
			case 2:
				finaleflat = "SFLR6_1";
				finaletext = texts[1];
				break;
			case 3:
				finaleflat = "MFLR8_4";
				finaletext = texts[2];
				break;
			case 4:
				finaleflat = "MFLR8_3";
				finaletext = texts[3];
				break;
			default:
				// Ouch.
				break;
			}
			break;
		}

			// DOOM II and missions packs with E1, M34
		case commercial:
		case pack_xbla:
		case pack_tnt:
		case pack_plut: {
			S.ChangeMusic(musicenum_t.mus_read_m, true);

			switch (DS.gamemap) {
			case 6:
				finaleflat = "SLIME16";
				finaletext = texts[0];
				break;
			case 11:
				finaleflat = "RROCK14";
				finaletext = texts[1];
				break;
			case 20:
				finaleflat = "RROCK07";
				finaleflat = texts[2];
				break;
			case 30:
				finaleflat = "RROCK17";
				finaletext = texts[3];
				break;
			case 15:
				finaleflat = "RROCK13";
				finaletext = texts[4];
				break;
			case 31:
				finaleflat = "RROCK19";
				finaletext = texts[5];
				break;
			default:
				// Ouch.
				break;
			}
			break;
		}

			// Indeterminate.
		default:
			S.ChangeMusic(musicenum_t.mus_read_m, true);
			finaleflat = "F_SKY1"; // Not used anywhere else.
			finaletext = doom2_text[1];
			; // FIXME - other text, music?
			break;
		}

		finalestage = 0;
		finalecount = 0;

	}

	public boolean Responder(event_t event) {
		if (finalestage == 2)
			return CastResponder(event);

		return false;
	}

	/**
	 * F_Ticker
	 */

	public void Ticker() {
		int i;

		// check for skipping
		if ((DS.isCommercial()) && (finalecount > 50)) {
			// go on to the next level
			for (i = 0; i < MAXPLAYERS; i++)
				if (DS.players[i].cmd.buttons != 0)
					break;

			if (i < MAXPLAYERS) {
				if (DS.gamemap == 30)
					StartCast();
				else
					DG.setGameAction(gameaction_t.ga_worlddone);
			}
		}

		// advance animation
		finalecount++;

		if (finalestage == 2) {
			CastTicker();
			return;
		}

		if (DS.isCommercial())
			return;
		// MAES: this is when we can transition to bunny.
		if ((finalestage == 0)
				&& finalecount > finaletext.length() * TEXTSPEED + TEXTWAIT) {
			finalecount = 0;
			finalestage = 1;
			DS.wipegamestate = gamestate_t.GS_MINUS_ONE; // force a wipe
			if (DS.gameepisode == 3)

				S.StartMusic(musicenum_t.mus_bunny);
		}
	}

	//
	// F_TextWrite
	//

	// #include "hu_stuff.h"
	patch_t[] hu_font;

	@SuppressWarnings("unchecked")
    public void TextWrite() {
		T src;
		//V dest;
		int w;
		int count;
		char[] ch;
		int c;
		int cx;
		int cy;

		// erase the entire screen to a tiled background
		src = (T)((flat_t) W.CacheLumpName(finaleflat, PU_CACHE, flat_t.class)).data;
		//dest = V.getScreen(DoomVideoRenderer.SCREEN_FG);

		for (int y = 0; y < SCREENHEIGHT; y+=64) {
			
			int y_maxdraw=Math.min(SCREENHEIGHT-y, 64);
			
			// Draw whole blocks.
			for (int x = 0; x < SCREENWIDTH; x+=64) {
				int x_maxdraw=Math.min(SCREENWIDTH-x, 64);
				V.DrawBlock(x, y, DoomVideoRenderer.SCREEN_FG, x_maxdraw,y_maxdraw,
						src);
			}
		}

		V.MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT);

		// draw some of the text onto the screen
		cx = 10;
		cy = 10;
		ch = finaletext.toCharArray();

		count = (finalecount - 10) / TEXTSPEED;
		if (count < 0)
			count = 0;

		// _D_: added min between count and ch.length, so that the text is not
		// written all at once
		for (int i = 0; i < Math.min(ch.length, count); i++)

		{
			c = ch[i];
			if (c == 0)
				break;
			if (c == '\n') {
				cx = 10;
				cy += 11;
				continue;
			}

			c = Character.toUpperCase(c) - HU_FONTSTART;
			if (c < 0 || c > HU_FONTSIZE) {
				cx += 4;
				continue;
			}

			w = hu_font[c].width;
			if (cx + w > SCREENWIDTH)
				break;
			V.DrawScaledPatch(cx, cy, 0, vs, hu_font[c]);
			cx += w;
		}

	}

	private final castinfo_t[] castorder;

	int castnum;
	int casttics;
	state_t caststate;
	boolean castdeath;
	int castframes;
	int castonmelee;
	boolean castattacking;

	//
	// F_StartCast
	//
	// extern gamestate_t wipegamestate;

	public void StartCast() {
		DS.wipegamestate = gamestate_t.GS_MINUS_ONE; // force a screen wipe
		castnum = 0;
		caststate = states[mobjinfo[castorder[castnum].type.ordinal()].seestate
				.ordinal()];
		casttics = (int) caststate.tics;
		castdeath = false;
		finalestage = 2;
		castframes = 0;
		castonmelee = 0;
		castattacking = false;
		S.ChangeMusic(musicenum_t.mus_evil, true);
	}

	//
	// F_CastTicker
	//
	public void CastTicker() {
		statenum_t st;
		sfxenum_t sfx;

		if (--casttics > 0)
			return; // not time to change state yet

		if (caststate.tics == -1 || caststate.nextstate == statenum_t.S_NULL
				|| caststate.nextstate == null) {
			// switch from deathstate to next monster
			castnum++;
			castdeath = false;
			if (castorder[castnum].name == null)
				castnum = 0;
			if (mobjinfo[castorder[castnum].type.ordinal()].seesound.ordinal() != 0)
				;
			S.StartSound(null,
					mobjinfo[castorder[castnum].type.ordinal()].seesound);
			caststate = states[mobjinfo[castorder[castnum].type.ordinal()].seestate
					.ordinal()];
			castframes = 0;
		} else {
			// just advance to next state in animation
			if (caststate == states[statenum_t.S_PLAY_ATK1.ordinal()]) {
				stopattack(); // Oh, gross hack!
				afterstopattack();
				return; // bye ...
			}

			st = caststate.nextstate;
			caststate = states[st.ordinal()];
			castframes++;

			// sound hacks....
			switch (st) {
			case S_PLAY_ATK1:
				sfx = sfxenum_t.sfx_dshtgn;
				break;
			case S_POSS_ATK2:
				sfx = sfxenum_t.sfx_pistol;
				break;
			case S_SPOS_ATK2:
				sfx = sfxenum_t.sfx_shotgn;
				break;
			case S_VILE_ATK2:
				sfx = sfxenum_t.sfx_vilatk;
				break;
			case S_SKEL_FIST2:
				sfx = sfxenum_t.sfx_skeswg;
				break;
			case S_SKEL_FIST4:
				sfx = sfxenum_t.sfx_skepch;
				break;
			case S_SKEL_MISS2:
				sfx = sfxenum_t.sfx_skeatk;
				break;
			case S_FATT_ATK8:
			case S_FATT_ATK5:
			case S_FATT_ATK2:
				sfx = sfxenum_t.sfx_firsht;
				break;
			case S_CPOS_ATK2:
			case S_CPOS_ATK3:
			case S_CPOS_ATK4:
				sfx = sfxenum_t.sfx_shotgn;
				break;
			case S_TROO_ATK3:
				sfx = sfxenum_t.sfx_claw;
				break;
			case S_SARG_ATK2:
				sfx = sfxenum_t.sfx_sgtatk;
				break;
			case S_BOSS_ATK2:
			case S_BOS2_ATK2:
			case S_HEAD_ATK2:
				sfx = sfxenum_t.sfx_firsht;
				break;
			case S_SKULL_ATK2:
				sfx = sfxenum_t.sfx_sklatk;
				break;
			case S_SPID_ATK2:
			case S_SPID_ATK3:
				sfx = sfxenum_t.sfx_shotgn;
				break;
			case S_BSPI_ATK2:
				sfx = sfxenum_t.sfx_plasma;
				break;
			case S_CYBER_ATK2:
			case S_CYBER_ATK4:
			case S_CYBER_ATK6:
				sfx = sfxenum_t.sfx_rlaunc;
				break;
			case S_PAIN_ATK3:
				sfx = sfxenum_t.sfx_sklatk;
				break;
			default:
				sfx = null;
				break;
			}

			if (sfx != null) // Fixed mute thanks to _D_ 8/6/2011
				S.StartSound(null, sfx);
		}

		if (castframes == 12) {
			// go into attack frame
			castattacking = true;
			if (castonmelee != 0)
				caststate = states[mobjinfo[castorder[castnum].type.ordinal()].meleestate
						.ordinal()];
			else
				caststate = states[mobjinfo[castorder[castnum].type.ordinal()].missilestate
						.ordinal()];
			castonmelee ^= 1;
			if (caststate == states[statenum_t.S_NULL.ordinal()]) {
				if (castonmelee != 0)
					caststate = states[mobjinfo[castorder[castnum].type
							.ordinal()].meleestate.ordinal()];
				else
					caststate = states[mobjinfo[castorder[castnum].type
							.ordinal()].missilestate.ordinal()];
			}
		}

		if (castattacking) {
			if (castframes == 24
					|| caststate == states[mobjinfo[castorder[castnum].type
							.ordinal()].seestate.ordinal()])

				stopattack();
		}

		afterstopattack();
	}

	protected void stopattack() {
		castattacking = false;
		castframes = 0;
		caststate = states[mobjinfo[castorder[castnum].type.ordinal()].seestate
				.ordinal()];
	}

	protected void afterstopattack() {
		casttics = (int) caststate.tics;
		if (casttics == -1)
			casttics = 15;
	}

	/**
	 * CastResponder
	 */

	public boolean CastResponder(event_t ev) {
		if (ev.type != evtype_t.ev_keydown)
			return false;

		if (castdeath)
			return true; // already in dying frames

		// go into death frame
		castdeath = true;
		caststate = states[mobjinfo[castorder[castnum].type.ordinal()].deathstate
				.ordinal()];
		casttics = (int) caststate.tics;
		castframes = 0;
		castattacking = false;
		if (mobjinfo[castorder[castnum].type.ordinal()].deathsound != null)
			S.StartSound(null,
					mobjinfo[castorder[castnum].type.ordinal()].deathsound);

		return true;
	}

	public void CastPrint(String text) {
		char[] ch;
		int c;
		int cx;
		int w;
		int width;

		// find width
		ch = text.toCharArray();
		width = 0;

		for (int i = 0; i < ch.length; i++) {
			c = ch[i];
			if (c == 0)
				break;
			c = Character.toUpperCase(c) - HU_FONTSTART;
			if (c < 0 || c > HU_FONTSIZE) {
				width += 4;
				continue;
			}

			w = hu_font[c].width;
			width += w;
		}

		// draw it
		cx = 160 - width / 2;
		// ch = text;
		for (int i = 0; i < ch.length; i++) {
			c = ch[i];
			if (c == 0)
				break;
			c = Character.toUpperCase(c) - HU_FONTSTART;
			if (c < 0 || c > HU_FONTSIZE) {
				cx += 4;
				continue;
			}

			w = hu_font[c].width;
			V.DrawScaledPatch(cx, 180, 0, vs, hu_font[c]);
			cx += w;
		}

	}

	/**
	 * F_CastDrawer
	 * 
	 * @throws IOException
	 */

	// public void V_DrawPatchFlipped (int x, int y, int scrn, patch_t patch);

	public void CastDrawer() {
		spritedef_t sprdef;
		spriteframe_t sprframe;
		int lump;
		boolean flip;
		patch_t patch = null;

		// erase the entire screen to a background
		V.DrawPatchSolidScaled(0, 0, SAFE_SCALE, SAFE_SCALE, 0,
				W.CachePatchName("BOSSBACK", PU_CACHE));

		this.CastPrint(castorder[castnum].name);

		// draw the current frame in the middle of the screen
		sprdef = SM.getSprite(caststate.sprite.ordinal());
		sprframe = sprdef.spriteframes[caststate.frame & FF_FRAMEMASK];
		lump = sprframe.lump[0];
		flip = eval(sprframe.flip[0]);
		// flip=false;
		// lump=0;

		patch = W.CachePatchNum(lump + SM.getFirstSpriteLump());

		if (flip)
			V.DrawScaledPatch(160, 170, 0 | DoomVideoRenderer.V_FLIPPEDPATCH,
					vs, patch);
		else
			V.DrawScaledPatch(160, 170, 0, vs, patch);
	}

	protected int laststage;

	/**
	 * F_BunnyScroll
	 */
	public void BunnyScroll() {
		int scrolled;
		int x;
		patch_t p1;
		patch_t p2;
		String name;
		int stage;

		p1 = W.CachePatchName("PFUB2", PU_LEVEL);
		p2 = W.CachePatchName("PFUB1", PU_LEVEL);

		V.MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT);

		scrolled = 320 - (finalecount - 230) / 2;
		if (scrolled > 320)
			scrolled = 320;
		if (scrolled < 0)
			scrolled = 0;

		for (x = 0; x < 320; x++) {
			if (x + scrolled < 320)
				V.DrawPatchColScaled(x, p1, x + scrolled, vs, 0);
			else
				V.DrawPatchColScaled(x, p2, x + scrolled - 320, vs, 0);
		}

		if (finalecount < 1130)
			return;
		if (finalecount < 1180) {
			V.DrawScaledPatch((320 - 13 * 8) / 2, (320 - 8 * 8) / 2, 0, vs,
					W.CachePatchName("END0", PU_CACHE));
			laststage = 0;
			return;
		}

		stage = (finalecount - 1180) / 5;
		if (stage > 6)
			stage = 6;
		if (stage > laststage) {
			S.StartSound(null, sfxenum_t.sfx_pistol);
			laststage = stage;
		}

		name = ("END" + stage);
		V.DrawScaledPatch((320 - 13 * 8) / 2, (320 - 8 * 8) / 2, 0, vs,
				W.CachePatchName(name, PU_CACHE));
	}

	//
	// F_Drawer
	//
	public void Drawer() {
		if (finalestage == 2) {
			CastDrawer();
			return;
		}

		if (finalestage == 0)
			TextWrite();
		else {
			switch (DS.gameepisode) {
			case 1:
				if (DS.isCommercial() || DS.isRegistered())
					V.DrawPatchSolidScaled(0, 0, this.SAFE_SCALE,
							this.SAFE_SCALE, 0,
							W.CachePatchName("CREDIT", PU_CACHE));
				else
					// Fun fact: Registered/Ultimate Doom has no "HELP2" lump.
					V.DrawPatchSolidScaled(0, 0, this.SAFE_SCALE,
							this.SAFE_SCALE, 0,
							W.CachePatchName("HELP2", PU_CACHE));
				break;
			case 2:
				V.DrawPatchSolidScaled(0, 0, this.SAFE_SCALE, this.SAFE_SCALE,
						0, W.CachePatchName("VICTORY2", PU_CACHE));
				break;
			case 3:
				BunnyScroll();
				break;
			case 4:
				V.DrawPatchSolidScaled(0, 0, this.SAFE_SCALE, this.SAFE_SCALE,
						0, W.CachePatchName("ENDPIC", PU_CACHE));
				break;
			}
		}

	}

	@SuppressWarnings("unchecked")
	public Finale(DoomStatus DC) {
		this.updateStatus(DC);
		hu_font = HU.getHUFonts();

		castinfo_t shit = new castinfo_t(CC_ZOMBIE, mobjtype_t.MT_POSSESSED);

		ArrayList<castinfo_t> crap = new ArrayList<castinfo_t>();
		crap.add(new castinfo_t(CC_ZOMBIE, mobjtype_t.MT_POSSESSED));
		crap.add(new castinfo_t(CC_SHOTGUN, mobjtype_t.MT_SHOTGUY));
		crap.add(new castinfo_t(CC_HEAVY, mobjtype_t.MT_CHAINGUY));
		crap.add(new castinfo_t(CC_IMP, mobjtype_t.MT_TROOP));
		crap.add(new castinfo_t(CC_DEMON, mobjtype_t.MT_SERGEANT));
		crap.add(new castinfo_t(CC_LOST, mobjtype_t.MT_SKULL));
		crap.add(new castinfo_t(CC_CACO, mobjtype_t.MT_HEAD));
		crap.add(new castinfo_t(CC_HELL, mobjtype_t.MT_KNIGHT));
		crap.add(new castinfo_t(CC_BARON, mobjtype_t.MT_BRUISER));
		crap.add(new castinfo_t(CC_ARACH, mobjtype_t.MT_BABY));
		crap.add(new castinfo_t(CC_PAIN, mobjtype_t.MT_PAIN));
		crap.add(new castinfo_t(CC_REVEN, mobjtype_t.MT_UNDEAD));
		crap.add(new castinfo_t(CC_MANCU, mobjtype_t.MT_FATSO));
		crap.add(new castinfo_t(CC_ARCH, mobjtype_t.MT_VILE));
		crap.add(new castinfo_t(CC_SPIDER, mobjtype_t.MT_SPIDER));
		crap.add(new castinfo_t(CC_CYBER, mobjtype_t.MT_CYBORG));
		crap.add(new castinfo_t(CC_HERO, mobjtype_t.MT_PLAYER));
		crap.add(new castinfo_t(null, null));

		castorder = C2JUtils
				.createArrayOfObjects(castinfo_t.class, crap.size());
		crap.toArray(castorder);

	}

	@Override
	public void updateStatus(DoomStatus<?,?> DC) {
		this.DG = DC.DG;
		this.DS = DC.DM;
		V = (DoomVideoRenderer<T,?>) DC.V;
		S = DC.S;
		HU = DC.HU;
		W = DC.W;
		SM = DC.SM;
	}

	// //////////////////////////VIDEO SCALE STUFF
	// ////////////////////////////////

	protected int SCREENWIDTH;
	protected int SCREENHEIGHT;
	protected int SAFE_SCALE;
	protected IVideoScale vs;

	@Override
	public void setVideoScale(IVideoScale vs) {
		this.vs = vs;
	}

	@Override
	public void initScaling() {
		this.SCREENHEIGHT = vs.getScreenHeight();
		this.SCREENWIDTH = vs.getScreenWidth();
		this.SAFE_SCALE = vs.getSafeScaling();

		// Pre-scale stuff.

	}

}

// /$Log
package f;

import data.mobjtype_t;

/**
 * Final DOOM 2 animation Casting by id Software. in order of appearance
 */

public class castinfo_t {
	String name;
	mobjtype_t type;

	public castinfo_t() {

	}

	public castinfo_t(String name, mobjtype_t type) {
		this.name = name;
		this.type = type;
	}

}

package f;

public interface IWiper {

    boolean ScreenWipe(int wipeno, int x, int y, int width, int height,
            int ticks);

    boolean EndScreen(int x, int y, int width, int height);

    boolean StartScreen(int x, int y, int width, int height);

}

package f;

public class point_t {
     public point_t(int x, int y) {
        this.x=x;
        this.y=y;
    }
     public   int     x;
     public  int     y;
        
    }

package f;

import doom.DoomStatus;
import m.IRandom;
import v.DoomVideoRenderer;
import v.IVideoScale;
import v.IVideoScaleAware;
import i.DoomStatusAware;
import i.DoomVideoInterface;

public abstract class AbstractWiper<T,V> implements IWiper, DoomStatusAware, IVideoScaleAware{
    
    //
    //                           SCREEN WIPE PACKAGE
    //

    /** These don't seem to be used anywhere */
    
    public static enum wipe
    {
        // simple gradual pixel change for 8-bit only
        // MAES: this transition isn't guaranteed to always terminate
        // see Chocolate Strife develpment. Unused in Doom anyway.
        ColorXForm,
        
        // weird screen melt
        Melt,  

        NUMWIPES
    };
    
    /** when false, stop the wipe */
    protected volatile boolean  go = false;

    protected V    wipe_scr_start;
    protected V    wipe_scr_end;
    protected V    wipe_scr;
    
////////////////////////////VIDEO SCALE STUFF ////////////////////////////////

    protected int SCREENWIDTH;
    protected int SCREENHEIGHT;
    protected int Y_SCALE;
    protected IVideoScale vs;


    @Override
    public void setVideoScale(IVideoScale vs) {
        this.vs=vs;
    }

    @Override
    public void initScaling() {
        this.SCREENHEIGHT=vs.getScreenHeight();
        this.SCREENWIDTH=vs.getScreenWidth();
        this.Y_SCALE=vs.getScalingY();

        // Pre-scale stuff.
    }

    ///////////////////// STATUS /////////////////////

    @SuppressWarnings("unchecked")
    @Override
    public void updateStatus(DoomStatus<?,?> DS){
    this.RND=DS.RND;
    this.V=(DoomVideoRenderer<T, V>) DS.V;
    this.VI=(DoomVideoInterface<V>) DS.VI;
    }
    
    IRandom RND;
    DoomVideoRenderer<T,V> V;
    DoomVideoInterface<V> VI;

    
}

package f;

import w.animenum_t;
import rr.patch_t;

//
//Animation.
//There is another anim_t used in p_spec.
//

public class anim_t {

        public anim_t(animenum_t type, int period, int nanims, point_t loc,
            int data1, int data2, patch_t[] p, int nexttic, int lastdrawn,
            int ctr, int state) {
        this.type = type;
        this.period = period;
        this.nanims = nanims;
        this.loc = loc;
        this.data1 = data1;
        this.data2 = data2;
        this.p = p;
        this.nexttic = nexttic;
        this.lastdrawn = lastdrawn;
        this.ctr = ctr;
        this.state = state;
    }
        // Partial constructor, only 4 first fields.
        public anim_t(animenum_t animAlways, int period, int nanims, point_t loc
               ) {
            this.type = animAlways;
            this.period = period;
            this.nanims = nanims;
            this.loc = loc;
        }
        
        // Partial constructor, only 5 first fields.
        public anim_t(animenum_t type, int period, int nanims, point_t loc, int data1
               ) {
            this.type = type;
            this.period = period;
            this.nanims = nanims;
            this.loc = loc;
            this.data1=data1;
        }
        
        public animenum_t  type;

        // period in tics between animations
        public int     period;

        // number of animation frames
        public int     nanims;

        // location of animation
        point_t loc;

        // ALWAYS: n/a,
        // RANDOM: period deviation (<256),
        // LEVEL: level
        public int     data1;

        // ALWAYS: n/a,
        // RANDOM: random base period,
        // LEVEL: n/a
        public int     data2; 

        // actual graphics for frames of animations
        //Maes: was pointer to array
        public patch_t[] p= new patch_t[3];

        // following must be initialized to zero before use!

        // next value of bcnt (used in conjunction with period)
        public int     nexttic;

        // last drawn animation frame
        public int     lastdrawn;

        // next frame number to animate
        public int     ctr;
        
        // used by RANDOM and LEVEL when animating
        public int     state;  

    } 

package f;

import i.DoomStatusAware;
import v.IVideoScaleAware;
import w.animenum_t;
import static data.Defines.TICRATE;

public abstract class AbstractEndLevel implements DoomStatusAware, IVideoScaleAware{
	
	//NET GAME STUFF

	public static final int NG_STATSY       =50;
	public static final int NG_SPACINGX        = 64;

	//DEATHMATCH STUFF
	public static final int DM_MATRIXX = 42;
	public static final int DM_MATRIXY =     68;

	public static final int DM_SPACINGX =    40;

	public static final int DM_TOTALSX =     269;

	public static final int DM_KILLERSX  =   10;
	public static final int DM_KILLERSY   =  100;
	public static final int DM_VICTIMSX    =     5;
	public static final int DM_VICTIMSY    = 50;

	// static point_t lnodes[NUMEPISODES][NUMMAPS] 
	final static public point_t[][] lnodes =
	{
	    // Episode 0 World Map
	    {
	    new point_t( 185, 164 ),   // location of level 0 (CJ)
	    new point_t( 148, 143 ),   // location of level 1 new point_t(CJ)
	    new point_t( 69, 122 ),    // location of level 2 new point_t(CJ)
	    new point_t( 209, 102 ),   // location of level 3 new point_t(CJ)
	    new point_t( 116, 89 ),    // location of level 4 new point_t(CJ)
	    new point_t( 166, 55 ),    // location of level 5 new point_t(CJ)
	    new point_t( 71, 56 ), // location of level 6 new point_t(CJ)
	    new point_t( 135, 29 ),    // location of level 7 new point_t(CJ)
	    new point_t( 71, 24 )  // location of level 8 new point_t(CJ)
	    },

	    // Episode 1 World Map should go here
	    {
	    new point_t( 254, 25 ),    // location of level 0 new point_t(CJ)
	    new point_t( 97, 50 ), // location of level 1 new point_t(CJ)
	    new point_t( 188, 64 ),    // location of level 2 new point_t(CJ)
	    new point_t( 128, 78 ),    // location of level 3 new point_t(CJ)
	    new point_t( 214, 92 ),    // location of level 4 new point_t(CJ)
	    new point_t( 133, 130 ),   // location of level 5 new point_t(CJ)
	    new point_t( 208, 136 ),   // location of level 6 new point_t(CJ)
	    new point_t( 148, 140 ),   // location of level 7 new point_t(CJ)
	    new point_t( 235, 158 )    // location of level 8 new point_t(CJ)
	    },

	    // Episode 2 World Map should go here
	    {
	    new point_t( 156, 168 ),   // location of level 0 new point_t(CJ)
	    new point_t( 48, 154 ),    // location of level 1 new point_t(CJ)
	    new point_t( 174, 95 ),    // location of level 2 new point_t(CJ)
	    new point_t( 265, 75 ),    // location of level 3 new point_t(CJ)
	    new point_t( 130, 48 ),    // location of level 4 new point_t(CJ)
	    new point_t( 279, 23 ),    // location of level 5 new point_t(CJ)
	    new point_t( 198, 48 ),    // location of level 6 new point_t(CJ)
	    new point_t( 140, 25 ),    // location of level 7 new point_t(CJ)
	    new point_t( 281, 136 )    // location of level 8 new point_t(CJ)
	    }

	};

	//
	//Animation locations for episode 0 (1).
	//Using patches saves a lot of space,
	//as they replace 320x200 full screen frames.
	//
	
	public static  final anim_t[] epsd0animinfo =
	{
	 new anim_t(animenum_t.ANIM_ALWAYS, TICRATE/3, 3, new point_t( 224, 104 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 184, 160 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 112, 136 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 72, 112 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3, new point_t( 88, 96 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 64, 48 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 192, 40 ) ),
	  new anim_t(animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 136, 16 ) ),
	  new anim_t(animenum_t. ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 80, 16 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 64, 24 ) )
	};

	public static final anim_t[] epsd1animinfo =
	{
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 1,  new point_t( 128, 136 ), 1 ),
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 1,  new point_t( 128, 136 ), 2 ),
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 1,  new point_t( 128, 136 ), 3 ),
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 1, new point_t( 128, 136 ), 4 ),
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 1,  new point_t(128, 136 ), 5 ),
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 1,  new point_t( 128, 136 ), 6 ),
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 1,  new point_t( 128, 136 ), 7 ),
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 3, new point_t( 192, 144 ), 8 ),
	  new anim_t( animenum_t.ANIM_LEVEL, TICRATE/3, 1,  new point_t( 128, 136 ), 8 )
	};

	public static final anim_t[] epsd2animinfo =
	{
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 104, 168 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 40, 136 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t( 160, 96 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3,  new point_t(104, 80 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/3, 3, new point_t( 120, 32 ) ),
	  new anim_t( animenum_t.ANIM_ALWAYS, TICRATE/4, 3,  new point_t( 40, 0 ) )
	};

	/*static int NUMANIMS[NUMEPISODES] =
	{
	 sizeof(epsd0animinfo)/sizeof(anim_t),
	 sizeof(epsd1animinfo)/sizeof(anim_t),
	 sizeof(epsd2animinfo)/sizeof(anim_t)
	};*/

	// MAES: cute, but we can do it in a more Java-friendly way :-p

	public static final int[] NUMANIMS={epsd0animinfo.length,epsd1animinfo.length,epsd2animinfo.length};

	/** ATTENTION: there's a difference between these "anims" and those used in p_spec.c */

	public static final anim_t[][] anims =
	{
	 epsd0animinfo,
	 epsd1animinfo,
	 epsd2animinfo
	};

}

package f;

import v.DoomVideoRenderer;
import doom.DoomMain;

public abstract class Wiper<T,V> extends AbstractWiper<T,V> {

    static final String rcsid = "$Id: Wiper.java,v 1.18 2012/09/24 17:16:23 velktron Exp $";
    
    protected wipefun[] wipes;
    
    public Wiper(DoomMain<T,V> DC){
        this.updateStatus(DC);
    }
    
    public static final class HiColor extends Wiper<byte[],short[]>{

        public HiColor(DoomMain<byte[], short[]> DC) {
            super(DC);
            wipes=new wipefun[]{
                    new wipe_initColorXForm(), new wipe_doColorXForm(), new wipe_exitColorXForm(),
                    new wipe_initMelt(), new wipe_doMelt(), new wipe_exitMelt()
                    };
        }
        
        /** Those guys sure have an obsession with shit...this is supposed to do some
         * lame-ass transpose.
         * 
         * @param array
         * @param width
         * @param height
         */
        
        protected final void
        shittyColMajorXform
        ( short[]    array,
          int       width,
          int       height )
        {
            int     x;
            int     y;
            short[]  dest;

            dest = new short[width*height];

            for(y=0;y<height;y++)
            for(x=0;x<width;x++){
                dest[x*height+y] = array[y*width+x];
                //dest[(1+x)*height+y] = array[y*width+(1+x)];
            }
            System.arraycopy(dest, 0, array, 0, width*height);

            //Z_Free(dest);

        }
        
        class wipe_doColorXForm implements wipefun{
            
            public boolean
        invoke
        ( int   width,
          int   height,
          int   ticks )
        {
            boolean changed;
            short[]   w=wipe_scr;
            short[]   e=wipe_scr_end;
            int     newval;

            changed = false;
            int pw =0;// wipe_scr;
            int pe = 0; //wipe_scr_end;
            
            while (pw!=width*height)
            {
            if (w[pw] != e[pe])
            {
                if (w[pw] > e[pe])
                {
                newval = w[pw] - ticks;
                if (newval < e[pe])
                    w[pw] = e[pe];
                else
                    w[pw] = (byte) newval;
                changed = true;
                }
                else if (w[pw] < e[pe])
                {
                newval = w[pw] + ticks;
                if (newval > e[pe])
                    w[pw] = e[pe];
                else
                    w[pw] = (byte) newval;
                changed = true;
                }
            }
            pw++;
            pe++;
            }

            return !changed;

        }
        }
    
        class wipe_doMelt implements wipefun{
            public boolean
            invoke
        ( int   width,
          int   height,
          int   ticks )
        {
                
            //   int w2=2*width;
            //    int w3=3*width;
            //    int w4=4*width;

            int     dy;
            int     idx;
            
            // Indexex to short* ?! WTF... 
            int  ps;
            int  pd;
            
            short[] s;//=wipe_scr_end;
            short[] d=wipe_scr;
            
            boolean done = true;

            //width=2;

            while (ticks-->0)
            {
            for (int i=0;i<width;i++)
            {
                // Column won't start yet.
                if (y[i]<0)
                {
                y[i]++; done = false;
                }
                else if (y[i] < height)
                {
                    
                    
                dy = (y[i] < 16*Y_SCALE) ? y[i]+Y_SCALE : 8*Y_SCALE;
                if (y[i]+dy >= height) dy = height - y[i];
                ps = i*height+y[i];// &((short *)wipe_scr_end)[i*height+y[i]];
                pd = y[i]*width+i;//&((short *)wipe_scr)[y[i]*width+i];
                idx = 0;

                s=wipe_scr_end;
                

                
                // MAES: this part should draw the END SCREEN "behind" the melt.
                for (int j=dy;j>0;j--)
                {
                    d[pd+idx] = s[ps++];
                    idx += width;
                }
                y[i] += dy;
                s=wipe_scr_start;
                ps = i*height; //&((short *)wipe_scr_start)[i*height];
                pd = y[i]*width+i; //&((short *)wipe_scr)[y[i]*width+i];
                idx = 0;

                // This draws a column shifted by y[i]
                
                for (int j=height-y[i];j>0;j--)
                {
                    d[pd+idx] = s[ps++];
                    idx+=width;
                }
                done = false;
                }
            }
            }

            return done;

        }
        }
    }
    
    public static final class Indexed extends Wiper<byte[],byte[]>{

        public Indexed(DoomMain<byte[], byte[]> DC) {
            super(DC);
            wipes=new wipefun[]{
                    new wipe_initColorXForm(), new wipe_doColorXForm(), new wipe_exitColorXForm(),
                    new wipe_initMelt(), new wipe_doMelt(), new wipe_exitMelt()
                    };
        }
        
        /** Those guys sure have an obsession with shit...this is supposed to do some
         * lame-ass transpose.
         * 
         * @param array
         * @param width
         * @param height
         */
        
        protected final void
        shittyColMajorXform
        ( byte[]    array,
          int       width,
          int       height )
        {
            int     x;
            int     y;
            byte[]  dest;

            dest = new byte[width*height];

            for(y=0;y<height;y++)
            for(x=0;x<width;x++){
                dest[x*height+y] = array[y*width+x];
                //dest[(1+x)*height+y] = array[y*width+(1+x)];
            }
            System.arraycopy(dest, 0, array, 0, width*height);

            //Z_Free(dest);

        }
        
        class wipe_doColorXForm implements wipefun{
            
            public boolean
        invoke
        ( int   width,
          int   height,
          int   ticks )
        {
            boolean changed;
            byte[]   w=wipe_scr;
            byte[]   e=wipe_scr_end;
            int     newval;

            changed = false;
            int pw =0;// wipe_scr;
            int pe = 0; //wipe_scr_end;
            
            while (pw!=width*height)
            {
            if (w[pw] != e[pe])
            {
                if (w[pw] > e[pe])
                {
                newval = w[pw] - ticks;
                if (newval < e[pe])
                    w[pw] = e[pe];
                else
                    w[pw] = (byte) newval;
                changed = true;
                }
                else if (w[pw] < e[pe])
                {
                newval = w[pw] + ticks;
                if (newval > e[pe])
                    w[pw] = e[pe];
                else
                    w[pw] = (byte) newval;
                changed = true;
                }
            }
            pw++;
            pe++;
            }

            return !changed;

        }
        }
    
        class wipe_doMelt implements wipefun{
            public boolean
            invoke
        ( int   width,
          int   height,
          int   ticks )
        {
                
            //   int w2=2*width;
            //    int w3=3*width;
            //    int w4=4*width;

            int     dy;
            int     idx;
            
            // Indexex to short* ?! WTF... 
            int  ps;
            int  pd;
            
            byte[] s;//=wipe_scr_end;
            byte[] d=wipe_scr;
            
            boolean done = true;

            //width=2;

            while (ticks-->0)
            {
            for (int i=0;i<width;i++)
            {
                // Column won't start yet.
                if (y[i]<0)
                {
                y[i]++; done = false;
                }
                else if (y[i] < height)
                {
                    
                    
                dy = (y[i] < 16*Y_SCALE) ? y[i]+Y_SCALE : 8*Y_SCALE;
                if (y[i]+dy >= height) dy = height - y[i];
                ps = i*height+y[i];// &((short *)wipe_scr_end)[i*height+y[i]];
                pd = y[i]*width+i;//&((short *)wipe_scr)[y[i]*width+i];
                idx = 0;

                s=wipe_scr_end;
                

                
                // MAES: this part should draw the END SCREEN "behind" the melt.
                for (int j=dy;j>0;j--)
                {
                    d[pd+idx] = s[ps++];
                    idx += width;
                }
                y[i] += dy;
                s=wipe_scr_start;
                ps = i*height; //&((short *)wipe_scr_start)[i*height];
                pd = y[i]*width+i; //&((short *)wipe_scr)[y[i]*width+i];
                idx = 0;

                // This draws a column shifted by y[i]
                
                for (int j=height-y[i];j>0;j--)
                {
                    d[pd+idx] = s[ps++];
                    idx+=width;
                }
                done = false;
                }
            }
            }

            return done;

        }
        }
    }
    
    public static final class TrueColor extends Wiper<byte[],int[]>{

        public TrueColor(DoomMain<byte[], int[]> DC) {
            super(DC);
            wipes=new wipefun[]{
                    new wipe_initColorXForm(), new wipe_doColorXForm(), new wipe_exitColorXForm(),
                    new wipe_initMelt(), new wipe_doMelt(), new wipe_exitMelt()
                    };
        }
        
        /** Those guys sure have an obsession with shit...this is supposed to do some
         * lame-ass transpose.
         * 
         * @param array
         * @param width
         * @param height
         */
        
        protected final void
        shittyColMajorXform
        ( int[]    array,
          int       width,
          int       height )
        {
            int     x;
            int     y;
            int[]  dest;

            dest = new int[width*height];

            for(y=0;y<height;y++)
            for(x=0;x<width;x++){
                dest[x*height+y] = array[y*width+x];
                //dest[(1+x)*height+y] = array[y*width+(1+x)];
            }
            System.arraycopy(dest, 0, array, 0, width*height);

            //Z_Free(dest);

        }
        
        class wipe_doColorXForm implements wipefun{
            
            public boolean
        invoke
        ( int   width,
          int   height,
          int   ticks )
        {
            boolean changed;
            int[]   w=wipe_scr;
            int[]   e=wipe_scr_end;
            int     newval;

            changed = false;
            int pw =0;// wipe_scr;
            int pe = 0; //wipe_scr_end;
            
            while (pw!=width*height)
            {
            if (w[pw] != e[pe])
            {
                if (w[pw] > e[pe])
                {
                newval = w[pw] - ticks;
                if (newval < e[pe])
                    w[pw] = e[pe];
                else
                    w[pw] = (byte) newval;
                changed = true;
                }
                else if (w[pw] < e[pe])
                {
                newval = w[pw] + ticks;
                if (newval > e[pe])
                    w[pw] = e[pe];
                else
                    w[pw] = (byte) newval;
                changed = true;
                }
            }
            pw++;
            pe++;
            }

            return !changed;

        }
        }
    
        class wipe_doMelt implements wipefun{
            public boolean
            invoke
        ( int   width,
          int   height,
          int   ticks )
        {
                
            //   int w2=2*width;
            //    int w3=3*width;
            //    int w4=4*width;

            int     dy;
            int     idx;
            
            // Indexex to short* ?! WTF... 
            int  ps;
            int  pd;
            
            int[] s;//=wipe_scr_end;
            int[] d=wipe_scr;
            
            boolean done = true;

            //width=2;

            while (ticks-->0)
            {
            for (int i=0;i<width;i++)
            {
                // Column won't start yet.
                if (y[i]<0)
                {
                y[i]++; done = false;
                }
                else if (y[i] < height)
                {
                    
                    
                dy = (y[i] < 16*Y_SCALE) ? y[i]+Y_SCALE : 8*Y_SCALE;
                if (y[i]+dy >= height) dy = height - y[i];
                ps = i*height+y[i];// &((short *)wipe_scr_end)[i*height+y[i]];
                pd = y[i]*width+i;//&((short *)wipe_scr)[y[i]*width+i];
                idx = 0;

                s=wipe_scr_end;
                

                
                // MAES: this part should draw the END SCREEN "behind" the melt.
                for (int j=dy;j>0;j--)
                {
                    d[pd+idx] = s[ps++];
                    idx += width;
                }
                y[i] += dy;
                s=wipe_scr_start;
                ps = i*height; //&((short *)wipe_scr_start)[i*height];
                pd = y[i]*width+i; //&((short *)wipe_scr)[y[i]*width+i];
                idx = 0;

                // This draws a column shifted by y[i]
                
                for (int j=height-y[i];j>0;j--)
                {
                    d[pd+idx] = s[ps++];
                    idx+=width;
                }
                done = false;
                }
            }
            }

            return done;

        }
        }
    }
    
    protected abstract void shittyColMajorXform( V array, int       width,  int       height );
    
    class wipe_initColorXForm implements wipefun{
        public boolean
        invoke
    ( int   width,
      int   height,
      int   ticks )
    {
        System.arraycopy(wipe_scr_start,0 ,wipe_scr, 0,width*height);
        return false;
    }
    
    }
   
    
    
    class wipe_exitColorXForm implements wipefun{
    public boolean
    invoke
    ( int   width,
      int   height,
      int   ticks )
    {
        return false;
    }
    }


    protected int[] y;

    class wipe_initMelt implements wipefun{
        public boolean
        invoke
    ( int   width,
      int   height,
      int   ticks )
    {
        int i, r;
        
        // copy start screen to main screen
        System.arraycopy(wipe_scr_start, 0,wipe_scr, 0,width*height);
        
        // makes this wipe faster (in theory)
        // to have stuff in column-major format
        shittyColMajorXform(wipe_scr_start, width, height);
        shittyColMajorXform(wipe_scr_end, width, height);
        
        // setup initial column positions
        // (y<0 => not ready to scroll yet)
        y = new int[width];
        
        y[0] = -(RND.M_Random()%16);
        
        for (int j=1;j<Y_SCALE;j++){
        	y[j]=y[j-1];
        }
        
        for (i=Y_SCALE;i<width;i+=Y_SCALE)
        {
            r = (RND.M_Random()%3) - 1;
            y[i] = y[i-1] + r;
            if (y[i] > 0) y[i] = 0;
            else if (y[i] == -16) y[i] = -15;
            
        	for (int j=1;j<Y_SCALE;j++){
        		y[i+j]=y[i];
        	}
        
        }

        return false;
    }
    }

    
    
    class wipe_exitMelt implements wipefun{
        public boolean
        invoke
    ( int   width,
      int   height,
      int   ticks )

    {
        y=null; //Z_Free(y);
        return false;
    }
    }

    /** Sets "from" screen and stores it in "screen 2"*/
    
    @Override
    public boolean
    StartScreen
    ( int   x,
      int   y,
      int   width,
      int   height )
    {
        wipe_scr_start = V.getScreen(DoomVideoRenderer.SCREEN_WS);
        //  byte[] screen_zero=V.getScreen(0);
        VI.ReadScreen(wipe_scr_start);
        
        //System.arraycopy(screen_zero,0,wipe_scr_start, 0, SCREENWIDTH*SCREENHEIGHT);
        return false;
    }

    /** Sets "to" screen and stores it to "screen 3" */

    @Override
    public boolean
    EndScreen
    ( int   x,
      int   y,
      int   width,
      int   height )
    {
        // Set end screen to "screen 3" and copy visible screen to it.
        wipe_scr_end = V.getScreen(DoomVideoRenderer.SCREEN_WE);
        VI.ReadScreen(wipe_scr_end);
        
        // Restore starting screen.
        V screen_zero= V.getScreen(DoomVideoRenderer.SCREEN_FG);        
        System.arraycopy(wipe_scr_start,0,screen_zero, 0, SCREENWIDTH*SCREENHEIGHT);
        return false;
    }
    @Override
    public boolean
    ScreenWipe
    ( int   wipeno,
      int   x,
      int   y,
      int   width,
      int   height,
      int   ticks )
    {
        boolean rc;
  
        //System.out.println("Ticks do "+ticks);

        // initial stuff
        if (!go)
        {
        go = true;
        //wipe_scr = new byte[width*height]; // DEBUG
        wipe_scr = V.getScreen(DoomVideoRenderer.SCREEN_FG);
        // HOW'S THAT FOR A FUNCTION POINTER, BIATCH?!
        (wipes[wipeno*3]).invoke(width, height, ticks);
        }

        // do a piece of wipe-in
        V.MarkRect(0, 0, width, height);
        rc = (wipes[wipeno*3+1]).invoke(width, height, ticks);
        // V.DrawBlock(x, y, 0, width, height, wipe_scr); // DEBUG

        // final stuff
        if (rc)
        {
        go = false;
        (wipes[wipeno*3+2]).invoke(width, height, ticks);
        }

        return !go;

    }

    
    /** Interface for ASS-WIPING functions */
    
    interface wipefun{
        public boolean invoke(int   width,
                int   height,
                int   ticks );
    }
    
}

package data;
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: dstrings.java,v 1.4 2010/10/01 16:47:51 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: dstrings.java,v $
// Revision 1.4  2010/10/01 16:47:51  velktron
// Fixed tab interception.
//
// Revision 1.3  2010/09/22 16:40:02  velktron
// MASSIVE changes in the status passing model.
// DoomMain and DoomGame unified.
// Doomstat merged into DoomMain (now status and game functions are one).
//
// Most of DoomMain implemented. Possible to attempt a "classic type" start but will stop when reading sprites.
//
// Revision 1.2  2010/07/22 15:37:53  velktron
// MAJOR changes in Menu system.
//
// Revision 1.1  2010/06/30 08:58:51  velktron
// Let's see if this stuff will finally commit....
//
//
// Most stuff is still  being worked on. For a good place to start and get an idea of what is being done, I suggest checking out the "testers" package.
//
// Revision 1.1  2010/06/29 11:07:34  velktron
// Release often, release early they say...
//
// Commiting ALL stuff done so far. A lot of stuff is still broken/incomplete, and there's still mixed C code in there. I suggest you load everything up in Eclpise and see what gives from there.
//
// A good place to start is the testers/ directory, where you  can get an idea of how a few of the implemented stuff works.
//
//
// DESCRIPTION:
//	Globally defined strings.
// 
//-----------------------------------------------------------------------------

import static doom.englsh.*;

public class dstrings{

//public static const char rcsid[] = "$Id: dstrings.java,v 1.4 2010/10/01 16:47:51 velktron Exp $";


    // Misc. other strings.
    public static final String SAVEGAMENAME=    "doomsav";
    
    /** File locations,  relative to current position.
     * Path names are OS-sensitive. 
     * Only really used with the -shdev command line parameter.
     * 
     * MAES: shouldn't those need path separator characters? :-S
     */
    
    
    public static final String DEVMAPS= "devmaps", DEVDATA ="devdata";


    // Not done in french?

    // QuitDOOM messages
    public static final int NUM_QUITMESSAGES= 22;


public static final String[] endmsg=
{
  // DOOM1
  QUITMSG,
  "please don't leave, there's more\ndemons to toast!",
  "let's beat it -- this is turning\ninto a bloodbath!",
  "i wouldn't leave if i were you.\ndos is much worse.",
  "you're trying to say you like dos\nbetter than me, right?",
  "don't leave yet -- there's a\ndemon around that corner!",
  "ya know, next time you come in here\ni'm gonna toast ya.",
  "go ahead and leave. see if i care.",

  // QuitDOOM II messages
  "you want to quit?\nthen, thou hast lost an eighth!",
  "don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!",
  "get outta here and go back\nto your boring programs.",
  "if i were your boss, i'd \n deathmatch ya in a minute!",
  "look, bud. you leave now\nand you forfeit your body count!",
  "just leave. when you come\nback, i'll be waiting with a bat.",
  "you're lucky i don't smack\nyou for thinking about leaving.",

  // FinalDOOM?
  "fuck you, pussy!\nget the fuck out!",
  "you quit and i'll jizz\nin your cystholes!",
  "if you leave, i'll make\nthe lord drink my jizz.",
  "hey, ron! can we say\n'fuck' in the game?",
  "i'd leave: this is just\nmore monsters and levels.\nwhat a load.",
  "suck it down, asshole!\nyou're a fucking wimp!",
  "don't quit now! we're \nstill spending your money!",

  // Internal debug. Different style, too.
  "THIS IS NO MESSAGE!\nPage intentionally left blank."
};
}


  



package data;

/**
 *   SoundFX struct.
 *    
 *   
 *
 */

public class sfxinfo_t {
	
		public sfxinfo_t(){
			
		}
	
        /** up to 6-character name */
        public String   name;

        /** Sfx singularity (only one at a time) */
        public boolean     singularity;

        /** Sfx priority */
        public int     priority;

        // referenced sound if a link
        // MAES: since in pure hackish C style, a "0" value would be used as a boolean, we'll need to distinguish more
        // unambiguously. So for querying, look at the "linked" boolean or a getter.
        public boolean linked;
        
        public sfxinfo_t  link;

        public sfxinfo_t getLink() {
            if (linked) return link;
            else return null;
        }

        public void setLink(sfxinfo_t link) {
            this.link=link;
        }
        
        // pitch if a link
        public int     pitch;

        // volume if a link
        public int     volume;

        /** sound data (used to be void*) */
        public byte[]  data;

        // this is checked every second to see if sound
        // can be thrown out (if 0, then decrement, if -1,
        // then throw out, if > 0, then it is in use)
        public int     usefulness;

        // lump number of sfx
        public int     lumpnum;

        public sfxinfo_t(String name, boolean singularity, int priority,
                sfxinfo_t link, int pitch, int volume, byte[] data,
                int usefulness, int lumpnum) {
            this.name = name;
            this.singularity = singularity;
            this.priority = priority;
            this.link = link;
            this.pitch = pitch;
            this.volume = volume;
            this.data = data;
            this.usefulness = usefulness;
            this.lumpnum = lumpnum;
        }
        
        /** MAES: Call this constructor if you don't want a cross-linked sound.
         * 
         * @param name
         * @param singularity
         * @param priority
         * @param pitch
         * @param volume
         * @param usefulness
         */
        
        public sfxinfo_t(String name, boolean singularity, int priority,
                int pitch, int volume, int usefulness) {
            this.name = name;
            this.singularity = singularity;
            this.priority = priority;
            this.linked = false;
            this.pitch = pitch;
            this.volume = volume;
            this.usefulness = usefulness;
        }
        
        public sfxinfo_t(String name, boolean singularity, int priority, boolean linked,
                int pitch, int volume, int usefulness) {
            this.name = name;
            this.singularity = singularity;
            this.priority = priority;
            this.linked = linked;
            this.pitch = pitch;
            this.volume = volume;
            this.usefulness = usefulness;
        }
        
        public int identify(sfxinfo_t[] array){
        	for (int i=0;i<array.length;i++){
        		if (array[i]==this){
        			return i;
        		}
        	}
        	// Duh
        	return 0;
        }
        
    };

package data;
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: doomtype.java,v 1.3 2011/02/11 00:11:13 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//	Simple basic typedefs, isolated here to make it easier
//	 separating modules.
//    
//-----------------------------------------------------------------------------


public class doomtype {

// C's "chars" are actually Java signed bytes.
public static byte MAXCHAR =((byte)0x7f);
public static short MAXSHORT=	((short)0x7fff);

// Max pos 32-bit int.
public static int MAXINT=((int)0x7fffffff);	
public static long MAXLONG=((long)0x7fffffff);
public static byte MINCHAR=((byte)0x80);
public static short MINSHORT=((short)0x8000);

// Max negative 32-bit integer.
public static int MININT=((int)0x80000000);
public static long MINLONG=((long)0x80000000);
}
package data;

//import m.define;
import static data.Limits.MAXINT;
import static data.Limits.MININT;
import static m.fixed_t.FRACBITS;
import static m.fixed_t.FRACUNIT;
import static m.fixed_t.MAPFRACUNIT;
import g.Keys;
import defines.ammotype_t;
import defines.card_t;
import doom.weapontype_t;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: Defines.java,v 1.48 2012/09/24 17:16:22 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//  Internally used data structures for virtually everything,
//   key definitions, lots of other stuff.
//
//-----------------------------------------------------------------------------

//#ifndef __DOOMDEF__
//#define __DOOMDEF__

//#include <stdio.h>
//#include <string.h>

//
// Global parameters/defines.
//
// DOOM version
public final class Defines{
    
    /** Seems to be 109 for shareware 1.9, wtf is this*/
public static final int VERSION =  109 ;

/** Some parts of the code may actually be better used as if in a UNIX environment */

public static final boolean NORMALUNIX =false;


/** If rangecheck is undefined,  ost parameter validation debugging code will not be compiled */
public static final boolean RANGECHECK=false;

// Do or do not use external soundserver.
// The sndserver binary to be run separately
//  has been introduced by Dave Taylor.
// The integrated sound support is experimental,
//  and unfinished. Default is synchronous.
// Experimental asynchronous timer based is
//  handled by SNDINTR. 
//#define SNDSERV  1
//#define SNDINTR  1

// Defines suck. C sucks.
// C++ might sucks for OOP, but it sure is a better C.
// So there.

// MAES: moved static defines out of here and into VideoScaleInfo.

// State updates, number of tics / second.
public static final int BASETICRATE = 35;
public static final int TIC_MUL = 1;
public static final int TICRATE = BASETICRATE*TIC_MUL;

//
// Difficulty/skill settings/filters.
//

// Skill flags.
public static int MTF_EASY =       1;
public static int MTF_NORMAL =     2;
public static int MTF_HARD =       4;

// Deaf monsters/do not react to sound.
public static int MTF_AMBUSH =8;

//Maes: this makes it a bit less retarded.
public static final int NUMCARDS=card_t.NUMCARDS.ordinal();


//Maes: this makes it a bit less retarded.
public static final int NUMWEAPONS=weapontype_t.NUMWEAPONS.ordinal();

//Maes: this makes it a bit less retarded.
public static final int NUMAMMO=ammotype_t.NUMAMMO.ordinal();

// Power up artifacts.
public static final int pw_invulnerability=0;
public static final int    pw_strength=1;
public static final int    pw_invisibility=2;
public static final int    pw_ironfeet=3;
public static final int    pw_allmap=4;
public static final int    pw_infrared=5;
public static final int    NUMPOWERS=6;


/** Power up durations,
 *  how many seconds till expiration,
 *  assuming TICRATE is 35 ticks/second.
 */
    public static final int INVULNTICS=(30*TICRATE),
    INVISTICS=(60*TICRATE),
    INFRATICS=(120*TICRATE),
    IRONTICS =(60*TICRATE);

// Center command from Heretic
public final static int TOCENTER=-8;

// from r_defs.h:



//Silhouette, needed for clipping Segs (mainly)
//and sprites representing things.
public static final int SIL_NONE =0;
public static final int SIL_BOTTOM     =1;
public static final int SIL_TOP  =       2;
public static final int SIL_BOTH    =    3;

//SKY, store the number for name.
static public final String SKYFLATNAME  ="F_SKY1";

// The sky map is 256*128*4 maps.
public static final int ANGLETOSKYSHIFT   = 22;

// From r_draw.c

// status bar height at bottom of screen
public static final int  SBARHEIGHT     = 32;


//
//Different vetween registered DOOM (1994) and
//Ultimate DOOM - Final edition (retail, 1995?).
//This is supposedly ignored for commercial
//release (aka DOOM II), which had 34 maps
//in one episode. So there.
public static final int NUMEPISODES=4;
public static final int NUMMAPS     =9;


//in tics
//U #define PAUSELEN        (TICRATE*2) 
//U #define SCORESTEP       100
//U #define ANIMPERIOD      32
//pixel distance from "(YOU)" to "PLAYER N"
//U #define STARDIST        10 
//U #define WK 1


// MAES 23/5/2011: moved SP_... stuff to EndLevel

public static final int    BACKUPTICS     = 12;




// From Zone:

//
//ZONE MEMORY
//PU - purge tags.
//Tags < 100 are not overwritten until freed.
public static final int PU_STATIC   =    1;   // static entire execution time
public static final int PU_SOUND    =    2;   // static while playing
public static final int PU_MUSIC   =     3;   // static while playing
public static final int PU_DAVE   =  4;   // anything else Dave wants static
public static final int PU_LEVEL   =     50;  // static until level exited
public static final int PU_LEVSPEC  =    51;    // a special thinker in a level
//Tags >= 100 are purgable whenever needed.
public static final int PU_PURGELEVEL =  100;
public static final int PU_CACHE     =   101;


// From hu_lib.h:

//background and foreground screen numbers
//different from other modules.
public static final int BG     =     1;
public static final int FG     =     0;

//font stuff
static public final char HU_CHARERASE  =  Keys.KEY_BACKSPACE;

public static final int HU_MAXLINES  =   4;
public static final int HU_MAXLINELENGTH  =  80;

// From hu_stuff.h

//
//Globally visible constants.
//
static public final byte HU_FONTSTART  =  '!'; // the first font characters
static public final byte HU_FONTEND  ='_'; // the last font characters

//Calculate # of glyphs in font.
public static final int HU_FONTSIZE = (HU_FONTEND - HU_FONTSTART + 1); 

static public final char HU_BROADCAST   = 5;

static public final char HU_MSGREFRESH =  Keys.KEY_ENTER;
static public final char HU_MSGX     =0;
static public final char HU_MSGY     =0;
static public final char HU_MSGWIDTH =64;  // in characters
static public final char HU_MSGHEIGHT  =  1;   // in lines

public static final int HU_MSGTIMEOUT =  (4*TICRATE);

public static final int SAVESTRINGSIZE = 24;

//
// Button/action code definitions.
// From d_event.h

     // Press "Fire".
    public static final int BT_ATTACK       = 1;
     // Use button, to open doors, activate switches.
    public static final int BT_USE      = 2;

     // Flag: game events, not really buttons.
    public static final int BT_SPECIAL      = 128;
    public static final int BT_SPECIALMASK  = 3;
     
     // Flag, weapon change pending.
     // If true, the next 3 bits hold weapon num.
    public static final int  BT_CHANGE       = 4;
     // The 3bit weapon mask and shift, convenience.
    public static final int  BT_WEAPONMASK   = (8+16+32);
    public static final int   BT_WEAPONSHIFT  = 3;

     // Pause the game.
    public static final int  BTS_PAUSE       = 1;
     // Save the game at each console.
    public static final int  BTS_SAVEGAME    = 2;

     // Savegame slot numbers
     //  occupy the second byte of buttons.    
    public static final int BTS_SAVEMASK    = (4+8+16);
    public static final int BTS_SAVESHIFT   = 2;
   

    
    
    //==================== Stuff from r_local.c =========================================

    
    public static final int FLOATSPEED        =(FRACUNIT*4);

    public static final int VIEWHEIGHT    =   (41*FRACUNIT);

    // mapblocks are used to check movement
    // against lines and things
    public static final int MAPBLOCKUNITS=    128;
    public static final int MAPBLOCKSIZE  =(MAPBLOCKUNITS*FRACUNIT);
    public static final int MAPBLOCKSHIFT =(FRACBITS+7);
    public static final int MAPBMASK      =(MAPBLOCKSIZE-1);
    public static final int MAPBTOFRAC=       (MAPBLOCKSHIFT-FRACBITS);
    public static final int BLOCKMAPPADDING=       8*FRACUNIT;

    // player radius for movement checking
    public static final int PLAYERRADIUS  =16*FRACUNIT;
    public static final int GRAVITY   =   MAPFRACUNIT;
    public static int USERANGE      =(64*FRACUNIT);
    public static int MELEERANGE    =   (64*FRACUNIT);
    public static int MISSILERANGE=(32*64*FRACUNIT);

    // follow a player exlusively for 3 seconds
    public static int   BASETHRESHOLD=      100;


    
    public static int PT_ADDLINES     =1;
    public static int PT_ADDTHINGS    =2;
    public static int PT_EARLYOUT     =4;
    
 //
 // P_MOBJ
 //
 public static int ONFLOORZ  =   MININT;
 public static int ONCEILINGZ    =   MAXINT;

 // Time interval for item respawning.
 public static int ITEMQUESIZE       =128;
 

    /** Indicate a leaf. e6y: support for extended nodes */
    public static final int NF_SUBSECTOR = 0x80000000;

    /** This is the regular leaf indicator. Use for reference/conversions */
    public static final int NF_SUBSECTOR_CLASSIC = 0x8000;

    
    
    /** Player states. */
    
    public static final int   PST_LIVE=0,     // Playing or camping.    
        PST_DEAD=1,        // Dead on the ground, view follows killer.

        PST_REBORN=2;            // Ready to restart/respawn???
 
    public static final int  FF_FULLBRIGHT =  0x8000;  // flag in thing->frame
    public static final int  FF_FRAMEMASK =   0x7fff;


 
static final String
rcsid = "$Id: Defines.java,v 1.48 2012/09/24 17:16:22 velktron Exp $";
}


package data;

import defines.statenum_t;
import data.sounds.sfxenum_t;

public class mobjinfo_t {
   
        public mobjinfo_t(int doomednum, statenum_t spawnstate, int spawnhealth,
                statenum_t seestate, sfxenum_t seesound, int reactiontime,
                sfxenum_t attacksound, statenum_t painstate,
                int painchance, sfxenum_t painsound,
                statenum_t meleestate, statenum_t missilestate,
                statenum_t deathstate, statenum_t xdeathstate,
                sfxenum_t deathsound, int speed, int radius, int height,
                int mass, int damage, sfxenum_t activesound, long flags,
                statenum_t raisestate) {
            super();
            this.doomednum = doomednum;
            this.spawnstate = spawnstate;
            this.spawnhealth = spawnhealth;
            this.seestate = seestate;
            this.seesound = seesound;
            this.reactiontime = reactiontime;
            this.attacksound = attacksound;
            this.painstate = painstate;
            this.painchance = painchance;
            this.painsound = painsound;
            this.meleestate = meleestate;
            this.missilestate = missilestate;
            this.deathstate = deathstate;
            this.xdeathstate = xdeathstate;
            this.deathsound = deathsound;
            this.speed = speed;
            this.radius = radius;
            this.height = height;
            this.mass = mass;
            this.damage = damage;
            this.activesound = activesound;
            this.flags = flags;
            this.raisestate = raisestate;
        }
        
        public int doomednum;
        public statenum_t spawnstate;
        public int spawnhealth;
        public statenum_t seestate;
        public sfxenum_t seesound;
        public int reactiontime;
        public sfxenum_t attacksound;
        public statenum_t painstate;
        public int painchance;
        public sfxenum_t painsound;
        public statenum_t meleestate;
        public statenum_t missilestate;
        public statenum_t deathstate;
        public statenum_t xdeathstate;
        public sfxenum_t deathsound;
        public int speed;
        public int radius;
        public int height;
        public int mass;
        public int damage;
        public sfxenum_t activesound;
        public long flags;
        public statenum_t raisestate;
    }

package data;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import w.CacheableDoomObject;

/**
 *  LineSeg, generated by splitting LineDefs
 * using partition lines selected by BSP builder.
 * MAES: this is the ON-DISK structure. The corresponding memory structure, 
 * segs_t, has fixed_t members. 
 */

public class mapseg_t implements CacheableDoomObject{
    
    public mapseg_t(){
        
    }

   public char     v1;
   public char     v2;
   public char     angle;      
   public char     linedef;
   public char     side;
   public char     offset;
   
   public static int sizeOf(){
       return 12;
   }
   
   @Override
   public void unpack(ByteBuffer buf)
           throws IOException {
       buf.order(ByteOrder.LITTLE_ENDIAN);
       this.v1 = buf.getChar();
       this.v2 = buf.getChar();
       this.angle=buf.getChar();       
       this.linedef=buf.getChar();
       this.side=buf.getChar();
       this.offset=buf.getChar();
      
   }
   
   public String toString(){
       return String.format("mapseg_t v1,2: %d %d ang: %d ld: %d sd: %d off: %d",
           (int)v1,(int)v2,(int)angle,(int)linedef,(int)side,(int)offset);
   }
   
 };

package data;
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: doomdata.java,v 1.4 2011/02/11 00:11:13 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//  all external data is defined here
//  most of the data is loaded into different structures at run time
//  some internal structures shared by many modules are here
//
//-----------------------------------------------------------------------------



    
// The most basic types we use, portability.
//#include "doomtype.h"

// Some global defines, that configure the game.


public class doomdata{
//
// Map level types.
// The following data structures define the persistent format
// used in the lumps of the WAD files.
//

// Lump order in a map WAD: each map needs a couple of lumps
// to provide a complete scene geometry description.
// Maes: this was defined as a typeless enum, probably intended to be used as cardinality?
// Turning it into "ML" enum or int consts.
public static enum ML
{
  ML_LABEL,		// A separator, name, ExMx or MAPxx
  ML_THINGS,		// Monsters, items..
  ML_LINEDEFS,		// LineDefs, from editing
  ML_SIDEDEFS,		// SideDefs, from editing
  ML_VERTEXES,		// Vertices, edited and BSP splits generated
  ML_SEGS,		// LineSegs, from LineDefs split by BSP
  ML_SSECTORS,		// SubSectors, list of LineSegs
  ML_NODES,		// BSP nodes
  ML_SECTORS,		// Sectors, from editing
  ML_REJECT,		// LUT, sector-sector visibility	
  ML_BLOCKMAP		// LUT, motion clipping, walls/grid element
};


// A single Vertex.
static class mapvertex_t
{
  short		x;
  short		y;
};


// A SideDef, defining the visual appearance of a wall,
// by setting textures and offsets.
static class  mapsidedef_t
{
  short		textureoffset;
  short		rowoffset;
  char[]		toptexture=new char[8];
  char[]		bottomtexture=new char[8];
  char[]		midtexture=new char[8];
  // Front sector, towards viewer.
  short		sector;
}



// A LineDef, as used for editing, and as input
// to the BSP builder.
static class maplinedef_t
{
  short		v1;
  short		v2;
  short		flags;
  short		special;
  short		tag;
  // sidenum[1] will be -1 if one sided
  int[]		sidenum=new int[2];		
} 


//
// LineDef attributes.
//

// Solid, is an obstacle.
public static final int ML_BLOCKING		=1;

// Blocks monsters only.
public static final int ML_BLOCKMONSTERS=	2;

// Backside will not be present at all
//  if not two sided.
public static final int ML_TWOSIDED		=4;

// If a texture is pegged, the texture will have
// the end exposed to air held constant at the
// top or bottom of the texture (stairs or pulled
// down things) and will move with a height change
// of one of the neighbor sectors.
// Unpegged textures allways have the first row of
// the texture at the top pixel of the line for both
// top and bottom textures (use next to windows).

// upper texture unpegged
public static final int ML_DONTPEGTOP=8;

// lower texture unpegged
public static final int ML_DONTPEGBOTTOM=	16	;

// In AutoMap: don't map as two sided: IT'S A SECRET!
public static final int ML_SECRET=		32;

// Sound rendering: don't let sound cross two of these.
public static final int ML_SOUNDBLOCK=		64;

// Don't draw on the automap at all.
public static final int ML_DONTDRAW=		128;

// Set if already seen, thus drawn in automap.
public static final int ML_MAPPED		=256;




// Sector definition, from editing.
class mapsector_t
{
  short		floorheight;
  short		ceilingheight;
  char[] floorpic=new char[8];
  char[]		ceilingpic=new char[8];
  short		lightlevel;
  short		special;
  short		tag;
};

// SubSector, as generated by BSP.
class mapsubsector_t
{
  short		numsegs;
  // Index of first one, segs are stored sequentially.
  short		firstseg;	
};


// LineSeg, generated by splitting LineDefs
// using partition lines selected by BSP builder.
class mapseg_t
{
  short		v1;
  short		v2;
  short		angle;		
  short		linedef;
  short		side;
  short		offset;
};



// BSP node structure.

// Indicate a leaf.
public static int	NF_SUBSECTOR	=0x8000;

class mapnode_t
{
  // Partition line from (x,y) to x+dx,y+dy)
  short		x;
  short		y;
  short		dx;
  short		dy;

  // Bounding box for each child,
  // clip against view frustum.
  short[][]		bbox=new short[2][4];

  // If NF_SUBSECTOR its a subsector,
  // else it's a node of another subtree.
  //Maes: used to be unsigned short
  int[] children=new int[2];

} ;

}
package data;

import static data.sounds.*;
import static m.fixed_t.*;
import static p.MobjFlags.*;
import defines.statenum_t;
import doom.think_t;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: info.java,v 1.13 2013/06/03 12:36:42 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

//
//-----------------------------------------------------------------------------

/** 
 * DESCRIPTION:
 *  Thing frame/state LUT, generated by multigen utilitiy.
 *  This one is the original DOOM version, preserved.
 * 
 * @author velktron
 *
 */

public class info{

public static final state_t[]	states = {
    // MAES: ATTENTION! The "null" state looks just like an imp. If you see it, then something's
    // wrong. When you check for "null" state, you should actually check whether something 
    // is set to S_NULL!
    new state_t(spritenum_t.SPR_TROO,0,-1,null,statenum_t.S_NULL,0,0),	// S_NULL
    // _D_: replaced "null" by "think_t.A_Light0" (see linuxdoom source)
    // I was trying to make the red fire around the gun apprear when we shoot
    // but I didn't succeed. This modification below is minor as I didn't see
    // any change in the game
    new state_t(spritenum_t.SPR_SHTG,4,0,think_t.A_Light0,statenum_t.S_NULL,0,0),	// S_LIGHTDONE
    new state_t(spritenum_t.SPR_PUNG,0,1,think_t.A_WeaponReady,statenum_t.S_PUNCH,0,0),	// S_PUNCH
    new state_t(spritenum_t.SPR_PUNG,0,1,think_t.A_Lower,statenum_t.S_PUNCHDOWN,0,0),	// S_PUNCHDOWN
    new state_t(spritenum_t.SPR_PUNG,0,1,think_t.A_Raise,statenum_t.S_PUNCHUP,0,0),	// S_PUNCHUP
    new state_t(spritenum_t.SPR_PUNG,1,4,null,statenum_t.S_PUNCH2,0,0),		// S_PUNCH1
    new state_t(spritenum_t.SPR_PUNG,2,4,think_t.A_Punch,statenum_t.S_PUNCH3,0,0),	// S_PUNCH2
    new state_t(spritenum_t.SPR_PUNG,3,5,null,statenum_t.S_PUNCH4,0,0),		// S_PUNCH3
    new state_t(spritenum_t.SPR_PUNG,2,4,null,statenum_t.S_PUNCH5,0,0),		// S_PUNCH4
    new state_t(spritenum_t.SPR_PUNG,1,5,think_t.A_ReFire,statenum_t.S_PUNCH,0,0),	// S_PUNCH5
    new state_t(spritenum_t.SPR_PISG,0,1,think_t.A_WeaponReady,statenum_t.S_PISTOL,0,0),// S_PISTOL
    new state_t(spritenum_t.SPR_PISG,0,1,think_t.A_Lower,statenum_t.S_PISTOLDOWN,0,0),	// S_PISTOLDOWN
    new state_t(spritenum_t.SPR_PISG,0,1,think_t.A_Raise,statenum_t.S_PISTOLUP,0,0),	// S_PISTOLUP
    new state_t(spritenum_t.SPR_PISG,0,4,null,statenum_t.S_PISTOL2,0,0),	// S_PISTOL1
    new state_t(spritenum_t.SPR_PISG,1,6,think_t.A_FirePistol,statenum_t.S_PISTOL3,0,0),// S_PISTOL2
    new state_t(spritenum_t.SPR_PISG,2,4,null,statenum_t.S_PISTOL4,0,0),	// S_PISTOL3
    new state_t(spritenum_t.SPR_PISG,1,5,think_t.A_ReFire,statenum_t.S_PISTOL,0,0),	// S_PISTOL4
    new state_t(spritenum_t.SPR_PISF,32768,7,think_t.A_Light1,statenum_t.S_LIGHTDONE,0,0),	// S_PISTOLFLASH
    new state_t(spritenum_t.SPR_SHTG,0,1,think_t.A_WeaponReady,statenum_t.S_SGUN,0,0),	// S_SGUN
    new state_t(spritenum_t.SPR_SHTG,0,1,think_t.A_Lower,statenum_t.S_SGUNDOWN,0,0),	// S_SGUNDOWN
    new state_t(spritenum_t.SPR_SHTG,0,1,think_t.A_Raise,statenum_t.S_SGUNUP,0,0),	// S_SGUNUP
    new state_t(spritenum_t.SPR_SHTG,0,3,null,statenum_t.S_SGUN2,0,0),	// S_SGUN1
    new state_t(spritenum_t.SPR_SHTG,0,7,think_t.A_FireShotgun,statenum_t.S_SGUN3,0,0),	// S_SGUN2
    new state_t(spritenum_t.SPR_SHTG,1,5,null,statenum_t.S_SGUN4,0,0),	// S_SGUN3
    new state_t(spritenum_t.SPR_SHTG,2,5,null,statenum_t.S_SGUN5,0,0),	// S_SGUN4
    new state_t(spritenum_t.SPR_SHTG,3,4,null,statenum_t.S_SGUN6,0,0),	// S_SGUN5
    new state_t(spritenum_t.SPR_SHTG,2,5,null,statenum_t.S_SGUN7,0,0),	// S_SGUN6
    new state_t(spritenum_t.SPR_SHTG,1,5,null,statenum_t.S_SGUN8,0,0),	// S_SGUN7
    new state_t(spritenum_t.SPR_SHTG,0,3,null,statenum_t.S_SGUN9,0,0),	// S_SGUN8
    new state_t(spritenum_t.SPR_SHTG,0,7,think_t.A_ReFire,statenum_t.S_SGUN,0,0),	// S_SGUN9
    new state_t(spritenum_t.SPR_SHTF,32768,4,think_t.A_Light1,statenum_t.S_SGUNFLASH2,0,0),	// S_SGUNFLASH1
    new state_t(spritenum_t.SPR_SHTF,32769,3,think_t.A_Light2,statenum_t.S_LIGHTDONE,0,0),	// S_SGUNFLASH2
    new state_t(spritenum_t.SPR_SHT2,0,1,think_t.A_WeaponReady,statenum_t.S_DSGUN,0,0),	// S_DSGUN
    new state_t(spritenum_t.SPR_SHT2,0,1,think_t.A_Lower,statenum_t.S_DSGUNDOWN,0,0),	// S_DSGUNDOWN
    new state_t(spritenum_t.SPR_SHT2,0,1,think_t.A_Raise,statenum_t.S_DSGUNUP,0,0),	// S_DSGUNUP
    new state_t(spritenum_t.SPR_SHT2,0,3,null,statenum_t.S_DSGUN2,0,0),	// S_DSGUN1
    new state_t(spritenum_t.SPR_SHT2,0,7,think_t.A_FireShotgun2,statenum_t.S_DSGUN3,0,0),	// S_DSGUN2
    new state_t(spritenum_t.SPR_SHT2,1,7,null,statenum_t.S_DSGUN4,0,0),	// S_DSGUN3
    new state_t(spritenum_t.SPR_SHT2,2,7,think_t.A_CheckReload,statenum_t.S_DSGUN5,0,0),	// S_DSGUN4
    new state_t(spritenum_t.SPR_SHT2,3,7,think_t.A_OpenShotgun2,statenum_t.S_DSGUN6,0,0),	// S_DSGUN5
    new state_t(spritenum_t.SPR_SHT2,4,7,null,statenum_t.S_DSGUN7,0,0),	// S_DSGUN6
    new state_t(spritenum_t.SPR_SHT2,5,7,think_t.A_LoadShotgun2,statenum_t.S_DSGUN8,0,0),	// S_DSGUN7
    new state_t(spritenum_t.SPR_SHT2,6,6,null,statenum_t.S_DSGUN9,0,0),	// S_DSGUN8
    new state_t(spritenum_t.SPR_SHT2,7,6,think_t.A_CloseShotgun2,statenum_t.S_DSGUN10,0,0),	// S_DSGUN9
    new state_t(spritenum_t.SPR_SHT2,0,5,think_t.A_ReFire,statenum_t.S_DSGUN,0,0),	// S_DSGUN10
    new state_t(spritenum_t.SPR_SHT2,1,7,null,statenum_t.S_DSNR2,0,0),	// S_DSNR1
    new state_t(spritenum_t.SPR_SHT2,0,3,null,statenum_t.S_DSGUNDOWN,0,0),	// S_DSNR2
    new state_t(spritenum_t.SPR_SHT2,32776,5,think_t.A_Light1,statenum_t.S_DSGUNFLASH2,0,0),	// S_DSGUNFLASH1
    new state_t(spritenum_t.SPR_SHT2,32777,4,think_t.A_Light2,statenum_t.S_LIGHTDONE,0,0),	// S_DSGUNFLASH2
    new state_t(spritenum_t.SPR_CHGG,0,1,think_t.A_WeaponReady,statenum_t.S_CHAIN,0,0),	// S_CHAIN
    new state_t(spritenum_t.SPR_CHGG,0,1,think_t.A_Lower,statenum_t.S_CHAINDOWN,0,0),	// S_CHAINDOWN
    new state_t(spritenum_t.SPR_CHGG,0,1,think_t.A_Raise,statenum_t.S_CHAINUP,0,0),	// S_CHAINUP
    new state_t(spritenum_t.SPR_CHGG,0,4,think_t.A_FireCGun,statenum_t.S_CHAIN2,0,0),	// S_CHAIN1
    new state_t(spritenum_t.SPR_CHGG,1,4,think_t.A_FireCGun,statenum_t.S_CHAIN3,0,0),	// S_CHAIN2
    new state_t(spritenum_t.SPR_CHGG,1,0,think_t.A_ReFire,statenum_t.S_CHAIN,0,0),	// S_CHAIN3
    new state_t(spritenum_t.SPR_CHGF,32768,5,think_t.A_Light1,statenum_t.S_LIGHTDONE,0,0),	// S_CHAINFLASH1
    new state_t(spritenum_t.SPR_CHGF,32769,5,think_t.A_Light2,statenum_t.S_LIGHTDONE,0,0),	// S_CHAINFLASH2
    new state_t(spritenum_t.SPR_MISG,0,1,think_t.A_WeaponReady,statenum_t.S_MISSILE,0,0),	// S_MISSILE
    new state_t(spritenum_t.SPR_MISG,0,1,think_t.A_Lower,statenum_t.S_MISSILEDOWN,0,0),	// S_MISSILEDOWN
    new state_t(spritenum_t.SPR_MISG,0,1,think_t.A_Raise,statenum_t.S_MISSILEUP,0,0),	// S_MISSILEUP
    new state_t(spritenum_t.SPR_MISG,1,8,think_t.A_GunFlash,statenum_t.S_MISSILE2,0,0),	// S_MISSILE1
    new state_t(spritenum_t.SPR_MISG,1,12,think_t.A_FireMissile,statenum_t.S_MISSILE3,0,0),	// S_MISSILE2
    new state_t(spritenum_t.SPR_MISG,1,0,think_t.A_ReFire,statenum_t.S_MISSILE,0,0),	// S_MISSILE3
    new state_t(spritenum_t.SPR_MISF,32768,3,think_t.A_Light1,statenum_t.S_MISSILEFLASH2,0,0),	// S_MISSILEFLASH1
    new state_t(spritenum_t.SPR_MISF,32769,4,null,statenum_t.S_MISSILEFLASH3,0,0),	// S_MISSILEFLASH2
    new state_t(spritenum_t.SPR_MISF,32770,4,think_t.A_Light2,statenum_t.S_MISSILEFLASH4,0,0),	// S_MISSILEFLASH3
    new state_t(spritenum_t.SPR_MISF,32771,4,think_t.A_Light2,statenum_t.S_LIGHTDONE,0,0),	// S_MISSILEFLASH4
    new state_t(spritenum_t.SPR_SAWG,2,4,think_t.A_WeaponReady,statenum_t.S_SAWB,0,0),	// S_SAW
    new state_t(spritenum_t.SPR_SAWG,3,4,think_t.A_WeaponReady,statenum_t.S_SAW,0,0),	// S_SAWB
    new state_t(spritenum_t.SPR_SAWG,2,1,think_t.A_Lower,statenum_t.S_SAWDOWN,0,0),	// S_SAWDOWN
    new state_t(spritenum_t.SPR_SAWG,2,1,think_t.A_Raise,statenum_t.S_SAWUP,0,0),	// S_SAWUP
    new state_t(spritenum_t.SPR_SAWG,0,4,think_t.A_Saw,statenum_t.S_SAW2,0,0),	// S_SAW1
    new state_t(spritenum_t.SPR_SAWG,1,4,think_t.A_Saw,statenum_t.S_SAW3,0,0),	// S_SAW2
    new state_t(spritenum_t.SPR_SAWG,1,0,think_t.A_ReFire,statenum_t.S_SAW,0,0),	// S_SAW3
    new state_t(spritenum_t.SPR_PLSG,0,1,think_t.A_WeaponReady,statenum_t.S_PLASMA,0,0),	// S_PLASMA
    new state_t(spritenum_t.SPR_PLSG,0,1,think_t.A_Lower,statenum_t.S_PLASMADOWN,0,0),	// S_PLASMADOWN
    new state_t(spritenum_t.SPR_PLSG,0,1,think_t.A_Raise,statenum_t.S_PLASMAUP,0,0),	// S_PLASMAUP
    new state_t(spritenum_t.SPR_PLSG,0,3,think_t.A_FirePlasma,statenum_t.S_PLASMA2,0,0),	// S_PLASMA1
    new state_t(spritenum_t.SPR_PLSG,1,20,think_t.A_ReFire,statenum_t.S_PLASMA,0,0),	// S_PLASMA2
    new state_t(spritenum_t.SPR_PLSF,32768,4,think_t.A_Light1,statenum_t.S_LIGHTDONE,0,0),	// S_PLASMAFLASH1
    new state_t(spritenum_t.SPR_PLSF,32769,4,think_t.A_Light1,statenum_t.S_LIGHTDONE,0,0),	// S_PLASMAFLASH2
    new state_t(spritenum_t.SPR_BFGG,0,1,think_t.A_WeaponReady,statenum_t.S_BFG,0,0),	// S_BFG
    new state_t(spritenum_t.SPR_BFGG,0,1,think_t.A_Lower,statenum_t.S_BFGDOWN,0,0),	// S_BFGDOWN
    new state_t(spritenum_t.SPR_BFGG,0,1,think_t.A_Raise,statenum_t.S_BFGUP,0,0),	// S_BFGUP
    new state_t(spritenum_t.SPR_BFGG,0,20,think_t.A_BFGsound,statenum_t.S_BFG2,0,0),	// S_BFG1
    new state_t(spritenum_t.SPR_BFGG,1,10,think_t.A_GunFlash,statenum_t.S_BFG3,0,0),	// S_BFG2
    new state_t(spritenum_t.SPR_BFGG,1,10,think_t.A_FireBFG,statenum_t.S_BFG4,0,0),	// S_BFG3
    new state_t(spritenum_t.SPR_BFGG,1,20,think_t.A_ReFire,statenum_t.S_BFG,0,0),	// S_BFG4
    new state_t(spritenum_t.SPR_BFGF,32768,11,think_t.A_Light1,statenum_t.S_BFGFLASH2,0,0),	// S_BFGFLASH1
    new state_t(spritenum_t.SPR_BFGF,32769,6,think_t.A_Light2,statenum_t.S_LIGHTDONE,0,0),	// S_BFGFLASH2
    new state_t(spritenum_t.SPR_BLUD,2,8,null,statenum_t.S_BLOOD2,0,0),	// S_BLOOD1
    new state_t(spritenum_t.SPR_BLUD,1,8,null,statenum_t.S_BLOOD3,0,0),	// S_BLOOD2
    new state_t(spritenum_t.SPR_BLUD,0,8,null,statenum_t.S_NULL,0,0),	// S_BLOOD3
    new state_t(spritenum_t.SPR_PUFF,32768,4,null,statenum_t.S_PUFF2,0,0),	// S_PUFF1
    new state_t(spritenum_t.SPR_PUFF,1,4,null,statenum_t.S_PUFF3,0,0),	// S_PUFF2
    new state_t(spritenum_t.SPR_PUFF,2,4,null,statenum_t.S_PUFF4,0,0),	// S_PUFF3
    new state_t(spritenum_t.SPR_PUFF,3,4,null,statenum_t.S_NULL,0,0),	// S_PUFF4
    new state_t(spritenum_t.SPR_BAL1,32768,4,null,statenum_t.S_TBALL2,0,0),	// S_TBALL1
    new state_t(spritenum_t.SPR_BAL1,32769,4,null,statenum_t.S_TBALL1,0,0),	// S_TBALL2
    new state_t(spritenum_t.SPR_BAL1,32770,6,null,statenum_t.S_TBALLX2,0,0),	// S_TBALLX1
    new state_t(spritenum_t.SPR_BAL1,32771,6,null,statenum_t.S_TBALLX3,0,0),	// S_TBALLX2
    new state_t(spritenum_t.SPR_BAL1,32772,6,null,statenum_t.S_NULL,0,0),	// S_TBALLX3
    new state_t(spritenum_t.SPR_BAL2,32768,4,null,statenum_t.S_RBALL2,0,0),	// S_RBALL1
    new state_t(spritenum_t.SPR_BAL2,32769,4,null,statenum_t.S_RBALL1,0,0),	// S_RBALL2
    new state_t(spritenum_t.SPR_BAL2,32770,6,null,statenum_t.S_RBALLX2,0,0),	// S_RBALLX1
    new state_t(spritenum_t.SPR_BAL2,32771,6,null,statenum_t.S_RBALLX3,0,0),	// S_RBALLX2
    new state_t(spritenum_t.SPR_BAL2,32772,6,null,statenum_t.S_NULL,0,0),	// S_RBALLX3
    new state_t(spritenum_t.SPR_PLSS,32768,6,null,statenum_t.S_PLASBALL2,0,0),	// S_PLASBALL
    new state_t(spritenum_t.SPR_PLSS,32769,6,null,statenum_t.S_PLASBALL,0,0),	// S_PLASBALL2
    new state_t(spritenum_t.SPR_PLSE,32768,4,null,statenum_t.S_PLASEXP2,0,0),	// S_PLASEXP
    new state_t(spritenum_t.SPR_PLSE,32769,4,null,statenum_t.S_PLASEXP3,0,0),	// S_PLASEXP2
    new state_t(spritenum_t.SPR_PLSE,32770,4,null,statenum_t.S_PLASEXP4,0,0),	// S_PLASEXP3
    new state_t(spritenum_t.SPR_PLSE,32771,4,null,statenum_t.S_PLASEXP5,0,0),	// S_PLASEXP4
    new state_t(spritenum_t.SPR_PLSE,32772,4,null,statenum_t.S_NULL,0,0),	// S_PLASEXP5
    new state_t(spritenum_t.SPR_MISL,32768,1,null,statenum_t.S_ROCKET,0,0),	// S_ROCKET
    new state_t(spritenum_t.SPR_BFS1,32768,4,null,statenum_t.S_BFGSHOT2,0,0),	// S_BFGSHOT
    new state_t(spritenum_t.SPR_BFS1,32769,4,null,statenum_t.S_BFGSHOT,0,0),	// S_BFGSHOT2
    new state_t(spritenum_t.SPR_BFE1,32768,8,null,statenum_t.S_BFGLAND2,0,0),	// S_BFGLAND
    new state_t(spritenum_t.SPR_BFE1,32769,8,null,statenum_t.S_BFGLAND3,0,0),	// S_BFGLAND2
    new state_t(spritenum_t.SPR_BFE1,32770,8,think_t.A_BFGSpray,statenum_t.S_BFGLAND4,0,0),	// S_BFGLAND3
    new state_t(spritenum_t.SPR_BFE1,32771,8,null,statenum_t.S_BFGLAND5,0,0),	// S_BFGLAND4
    new state_t(spritenum_t.SPR_BFE1,32772,8,null,statenum_t.S_BFGLAND6,0,0),	// S_BFGLAND5
    new state_t(spritenum_t.SPR_BFE1,32773,8,null,statenum_t.S_NULL,0,0),	// S_BFGLAND6
    new state_t(spritenum_t.SPR_BFE2,32768,8,null,statenum_t.S_BFGEXP2,0,0),	// S_BFGEXP
    new state_t(spritenum_t.SPR_BFE2,32769,8,null,statenum_t.S_BFGEXP3,0,0),	// S_BFGEXP2
    new state_t(spritenum_t.SPR_BFE2,32770,8,null,statenum_t.S_BFGEXP4,0,0),	// S_BFGEXP3
    new state_t(spritenum_t.SPR_BFE2,32771,8,null,statenum_t.S_NULL,0,0),	// S_BFGEXP4
    new state_t(spritenum_t.SPR_MISL,32769,8,think_t.A_Explode,statenum_t.S_EXPLODE2,0,0),	// S_EXPLODE1
    new state_t(spritenum_t.SPR_MISL,32770,6,null,statenum_t.S_EXPLODE3,0,0),	// S_EXPLODE2
    new state_t(spritenum_t.SPR_MISL,32771,4,null,statenum_t.S_NULL,0,0),	// S_EXPLODE3
    new state_t(spritenum_t.SPR_TFOG,32768,6,null,statenum_t.S_TFOG01,0,0),	// S_TFOG
    new state_t(spritenum_t.SPR_TFOG,32769,6,null,statenum_t.S_TFOG02,0,0),	// S_TFOG01
    new state_t(spritenum_t.SPR_TFOG,32768,6,null,statenum_t.S_TFOG2,0,0),	// S_TFOG02
    new state_t(spritenum_t.SPR_TFOG,32769,6,null,statenum_t.S_TFOG3,0,0),	// S_TFOG2
    new state_t(spritenum_t.SPR_TFOG,32770,6,null,statenum_t.S_TFOG4,0,0),	// S_TFOG3
    new state_t(spritenum_t.SPR_TFOG,32771,6,null,statenum_t.S_TFOG5,0,0),	// S_TFOG4
    new state_t(spritenum_t.SPR_TFOG,32772,6,null,statenum_t.S_TFOG6,0,0),	// S_TFOG5
    new state_t(spritenum_t.SPR_TFOG,32773,6,null,statenum_t.S_TFOG7,0,0),	// S_TFOG6
    new state_t(spritenum_t.SPR_TFOG,32774,6,null,statenum_t.S_TFOG8,0,0),	// S_TFOG7
    new state_t(spritenum_t.SPR_TFOG,32775,6,null,statenum_t.S_TFOG9,0,0),	// S_TFOG8
    new state_t(spritenum_t.SPR_TFOG,32776,6,null,statenum_t.S_TFOG10,0,0),	// S_TFOG9
    new state_t(spritenum_t.SPR_TFOG,32777,6,null,statenum_t.S_NULL,0,0),	// S_TFOG10
    new state_t(spritenum_t.SPR_IFOG,32768,6,null,statenum_t.S_IFOG01,0,0),	// S_IFOG
    new state_t(spritenum_t.SPR_IFOG,32769,6,null,statenum_t.S_IFOG02,0,0),	// S_IFOG01
    new state_t(spritenum_t.SPR_IFOG,32768,6,null,statenum_t.S_IFOG2,0,0),	// S_IFOG02
    new state_t(spritenum_t.SPR_IFOG,32769,6,null,statenum_t.S_IFOG3,0,0),	// S_IFOG2
    new state_t(spritenum_t.SPR_IFOG,32770,6,null,statenum_t.S_IFOG4,0,0),	// S_IFOG3
    new state_t(spritenum_t.SPR_IFOG,32771,6,null,statenum_t.S_IFOG5,0,0),	// S_IFOG4
    new state_t(spritenum_t.SPR_IFOG,32772,6,null,statenum_t.S_NULL,0,0),	// S_IFOG5
    new state_t(spritenum_t.SPR_PLAY,0,-1,null,statenum_t.S_NULL,0,0),	// S_PLAY
    new state_t(spritenum_t.SPR_PLAY,0,4,null,statenum_t.S_PLAY_RUN2,0,0),	// S_PLAY_RUN1
    new state_t(spritenum_t.SPR_PLAY,1,4,null,statenum_t.S_PLAY_RUN3,0,0),	// S_PLAY_RUN2
    new state_t(spritenum_t.SPR_PLAY,2,4,null,statenum_t.S_PLAY_RUN4,0,0),	// S_PLAY_RUN3
    new state_t(spritenum_t.SPR_PLAY,3,4,null,statenum_t.S_PLAY_RUN1,0,0),	// S_PLAY_RUN4
    new state_t(spritenum_t.SPR_PLAY,4,12,null,statenum_t.S_PLAY,0,0),	// S_PLAY_ATK1
    new state_t(spritenum_t.SPR_PLAY,32773,6,null,statenum_t.S_PLAY_ATK1,0,0),	// S_PLAY_ATK2
    new state_t(spritenum_t.SPR_PLAY,6,4,null,statenum_t.S_PLAY_PAIN2,0,0),	// S_PLAY_PAIN
    new state_t(spritenum_t.SPR_PLAY,6,4,think_t.A_Pain,statenum_t.S_PLAY,0,0),	// S_PLAY_PAIN2
    new state_t(spritenum_t.SPR_PLAY,7,10,null,statenum_t.S_PLAY_DIE2,0,0),	// S_PLAY_DIE1
    new state_t(spritenum_t.SPR_PLAY,8,10,think_t.A_PlayerScream,statenum_t.S_PLAY_DIE3,0,0),	// S_PLAY_DIE2
    new state_t(spritenum_t.SPR_PLAY,9,10,think_t.A_Fall,statenum_t.S_PLAY_DIE4,0,0),	// S_PLAY_DIE3
    new state_t(spritenum_t.SPR_PLAY,10,10,null,statenum_t.S_PLAY_DIE5,0,0),	// S_PLAY_DIE4
    new state_t(spritenum_t.SPR_PLAY,11,10,null,statenum_t.S_PLAY_DIE6,0,0),	// S_PLAY_DIE5
    new state_t(spritenum_t.SPR_PLAY,12,10,null,statenum_t.S_PLAY_DIE7,0,0),	// S_PLAY_DIE6
    new state_t(spritenum_t.SPR_PLAY,13,-1,null,statenum_t.S_NULL,0,0),	// S_PLAY_DIE7
    new state_t(spritenum_t.SPR_PLAY,14,5,null,statenum_t.S_PLAY_XDIE2,0,0),	// S_PLAY_XDIE1
    new state_t(spritenum_t.SPR_PLAY,15,5,think_t.A_XScream,statenum_t.S_PLAY_XDIE3,0,0),	// S_PLAY_XDIE2
    new state_t(spritenum_t.SPR_PLAY,16,5,think_t.A_Fall,statenum_t.S_PLAY_XDIE4,0,0),	// S_PLAY_XDIE3
    new state_t(spritenum_t.SPR_PLAY,17,5,null,statenum_t.S_PLAY_XDIE5,0,0),	// S_PLAY_XDIE4
    new state_t(spritenum_t.SPR_PLAY,18,5,null,statenum_t.S_PLAY_XDIE6,0,0),	// S_PLAY_XDIE5
    new state_t(spritenum_t.SPR_PLAY,19,5,null,statenum_t.S_PLAY_XDIE7,0,0),	// S_PLAY_XDIE6
    new state_t(spritenum_t.SPR_PLAY,20,5,null,statenum_t.S_PLAY_XDIE8,0,0),	// S_PLAY_XDIE7
    new state_t(spritenum_t.SPR_PLAY,21,5,null,statenum_t.S_PLAY_XDIE9,0,0),	// S_PLAY_XDIE8
    new state_t(spritenum_t.SPR_PLAY,22,-1,null,statenum_t.S_NULL,0,0),	// S_PLAY_XDIE9
    new state_t(spritenum_t.SPR_POSS,0,10,think_t.A_Look,statenum_t.S_POSS_STND2,0,0),	// S_POSS_STND
    new state_t(spritenum_t.SPR_POSS,1,10,think_t.A_Look,statenum_t.S_POSS_STND,0,0),	// S_POSS_STND2
    new state_t(spritenum_t.SPR_POSS,0,4,think_t.A_Chase,statenum_t.S_POSS_RUN2,0,0),	// S_POSS_RUN1
    new state_t(spritenum_t.SPR_POSS,0,4,think_t.A_Chase,statenum_t.S_POSS_RUN3,0,0),	// S_POSS_RUN2
    new state_t(spritenum_t.SPR_POSS,1,4,think_t.A_Chase,statenum_t.S_POSS_RUN4,0,0),	// S_POSS_RUN3
    new state_t(spritenum_t.SPR_POSS,1,4,think_t.A_Chase,statenum_t.S_POSS_RUN5,0,0),	// S_POSS_RUN4
    new state_t(spritenum_t.SPR_POSS,2,4,think_t.A_Chase,statenum_t.S_POSS_RUN6,0,0),	// S_POSS_RUN5
    new state_t(spritenum_t.SPR_POSS,2,4,think_t.A_Chase,statenum_t.S_POSS_RUN7,0,0),	// S_POSS_RUN6
    new state_t(spritenum_t.SPR_POSS,3,4,think_t.A_Chase,statenum_t.S_POSS_RUN8,0,0),	// S_POSS_RUN7
    new state_t(spritenum_t.SPR_POSS,3,4,think_t.A_Chase,statenum_t.S_POSS_RUN1,0,0),	// S_POSS_RUN8
    new state_t(spritenum_t.SPR_POSS,4,10,think_t.A_FaceTarget,statenum_t.S_POSS_ATK2,0,0),	// S_POSS_ATK1
    new state_t(spritenum_t.SPR_POSS,5,8,think_t.A_PosAttack,statenum_t.S_POSS_ATK3,0,0),	// S_POSS_ATK2
    new state_t(spritenum_t.SPR_POSS,4,8,null,statenum_t.S_POSS_RUN1,0,0),	// S_POSS_ATK3
    new state_t(spritenum_t.SPR_POSS,6,3,null,statenum_t.S_POSS_PAIN2,0,0),	// S_POSS_PAIN
    new state_t(spritenum_t.SPR_POSS,6,3,think_t.A_Pain,statenum_t.S_POSS_RUN1,0,0),	// S_POSS_PAIN2
    new state_t(spritenum_t.SPR_POSS,7,5,null,statenum_t.S_POSS_DIE2,0,0),	// S_POSS_DIE1
    new state_t(spritenum_t.SPR_POSS,8,5,think_t.A_Scream,statenum_t.S_POSS_DIE3,0,0),	// S_POSS_DIE2
    new state_t(spritenum_t.SPR_POSS,9,5,think_t.A_Fall,statenum_t.S_POSS_DIE4,0,0),	// S_POSS_DIE3
    new state_t(spritenum_t.SPR_POSS,10,5,null,statenum_t.S_POSS_DIE5,0,0),	// S_POSS_DIE4
    new state_t(spritenum_t.SPR_POSS,11,-1,null,statenum_t.S_NULL,0,0),	// S_POSS_DIE5
    new state_t(spritenum_t.SPR_POSS,12,5,null,statenum_t.S_POSS_XDIE2,0,0),	// S_POSS_XDIE1
    new state_t(spritenum_t.SPR_POSS,13,5,think_t.A_XScream,statenum_t.S_POSS_XDIE3,0,0),	// S_POSS_XDIE2
    new state_t(spritenum_t.SPR_POSS,14,5,think_t.A_Fall,statenum_t.S_POSS_XDIE4,0,0),	// S_POSS_XDIE3
    new state_t(spritenum_t.SPR_POSS,15,5,null,statenum_t.S_POSS_XDIE5,0,0),	// S_POSS_XDIE4
    new state_t(spritenum_t.SPR_POSS,16,5,null,statenum_t.S_POSS_XDIE6,0,0),	// S_POSS_XDIE5
    new state_t(spritenum_t.SPR_POSS,17,5,null,statenum_t.S_POSS_XDIE7,0,0),	// S_POSS_XDIE6
    new state_t(spritenum_t.SPR_POSS,18,5,null,statenum_t.S_POSS_XDIE8,0,0),	// S_POSS_XDIE7
    new state_t(spritenum_t.SPR_POSS,19,5,null,statenum_t.S_POSS_XDIE9,0,0),	// S_POSS_XDIE8
    new state_t(spritenum_t.SPR_POSS,20,-1,null,statenum_t.S_NULL,0,0),	// S_POSS_XDIE9
    new state_t(spritenum_t.SPR_POSS,10,5,null,statenum_t.S_POSS_RAISE2,0,0),	// S_POSS_RAISE1
    new state_t(spritenum_t.SPR_POSS,9,5,null,statenum_t.S_POSS_RAISE3,0,0),	// S_POSS_RAISE2
    new state_t(spritenum_t.SPR_POSS,8,5,null,statenum_t.S_POSS_RAISE4,0,0),	// S_POSS_RAISE3
    new state_t(spritenum_t.SPR_POSS,7,5,null,statenum_t.S_POSS_RUN1,0,0),	// S_POSS_RAISE4
    new state_t(spritenum_t.SPR_SPOS,0,10,think_t.A_Look,statenum_t.S_SPOS_STND2,0,0),	// S_SPOS_STND
    new state_t(spritenum_t.SPR_SPOS,1,10,think_t.A_Look,statenum_t.S_SPOS_STND,0,0),	// S_SPOS_STND2
    new state_t(spritenum_t.SPR_SPOS,0,3,think_t.A_Chase,statenum_t.S_SPOS_RUN2,0,0),	// S_SPOS_RUN1
    new state_t(spritenum_t.SPR_SPOS,0,3,think_t.A_Chase,statenum_t.S_SPOS_RUN3,0,0),	// S_SPOS_RUN2
    new state_t(spritenum_t.SPR_SPOS,1,3,think_t.A_Chase,statenum_t.S_SPOS_RUN4,0,0),	// S_SPOS_RUN3
    new state_t(spritenum_t.SPR_SPOS,1,3,think_t.A_Chase,statenum_t.S_SPOS_RUN5,0,0),	// S_SPOS_RUN4
    new state_t(spritenum_t.SPR_SPOS,2,3,think_t.A_Chase,statenum_t.S_SPOS_RUN6,0,0),	// S_SPOS_RUN5
    new state_t(spritenum_t.SPR_SPOS,2,3,think_t.A_Chase,statenum_t.S_SPOS_RUN7,0,0),	// S_SPOS_RUN6
    new state_t(spritenum_t.SPR_SPOS,3,3,think_t.A_Chase,statenum_t.S_SPOS_RUN8,0,0),	// S_SPOS_RUN7
    new state_t(spritenum_t.SPR_SPOS,3,3,think_t.A_Chase,statenum_t.S_SPOS_RUN1,0,0),	// S_SPOS_RUN8
    new state_t(spritenum_t.SPR_SPOS,4,10,think_t.A_FaceTarget,statenum_t.S_SPOS_ATK2,0,0),	// S_SPOS_ATK1
    new state_t(spritenum_t.SPR_SPOS,32773,10,think_t.A_SPosAttack,statenum_t.S_SPOS_ATK3,0,0),	// S_SPOS_ATK2
    new state_t(spritenum_t.SPR_SPOS,4,10,null,statenum_t.S_SPOS_RUN1,0,0),	// S_SPOS_ATK3
    new state_t(spritenum_t.SPR_SPOS,6,3,null,statenum_t.S_SPOS_PAIN2,0,0),	// S_SPOS_PAIN
    new state_t(spritenum_t.SPR_SPOS,6,3,think_t.A_Pain,statenum_t.S_SPOS_RUN1,0,0),	// S_SPOS_PAIN2
    new state_t(spritenum_t.SPR_SPOS,7,5,null,statenum_t.S_SPOS_DIE2,0,0),	// S_SPOS_DIE1
    new state_t(spritenum_t.SPR_SPOS,8,5,think_t.A_Scream,statenum_t.S_SPOS_DIE3,0,0),	// S_SPOS_DIE2
    new state_t(spritenum_t.SPR_SPOS,9,5,think_t.A_Fall,statenum_t.S_SPOS_DIE4,0,0),	// S_SPOS_DIE3
    new state_t(spritenum_t.SPR_SPOS,10,5,null,statenum_t.S_SPOS_DIE5,0,0),	// S_SPOS_DIE4
    new state_t(spritenum_t.SPR_SPOS,11,-1,null,statenum_t.S_NULL,0,0),	// S_SPOS_DIE5
    new state_t(spritenum_t.SPR_SPOS,12,5,null,statenum_t.S_SPOS_XDIE2,0,0),	// S_SPOS_XDIE1
    new state_t(spritenum_t.SPR_SPOS,13,5,think_t.A_XScream,statenum_t.S_SPOS_XDIE3,0,0),	// S_SPOS_XDIE2
    new state_t(spritenum_t.SPR_SPOS,14,5,think_t.A_Fall,statenum_t.S_SPOS_XDIE4,0,0),	// S_SPOS_XDIE3
    new state_t(spritenum_t.SPR_SPOS,15,5,null,statenum_t.S_SPOS_XDIE5,0,0),	// S_SPOS_XDIE4
    new state_t(spritenum_t.SPR_SPOS,16,5,null,statenum_t.S_SPOS_XDIE6,0,0),	// S_SPOS_XDIE5
    new state_t(spritenum_t.SPR_SPOS,17,5,null,statenum_t.S_SPOS_XDIE7,0,0),	// S_SPOS_XDIE6
    new state_t(spritenum_t.SPR_SPOS,18,5,null,statenum_t.S_SPOS_XDIE8,0,0),	// S_SPOS_XDIE7
    new state_t(spritenum_t.SPR_SPOS,19,5,null,statenum_t.S_SPOS_XDIE9,0,0),	// S_SPOS_XDIE8
    new state_t(spritenum_t.SPR_SPOS,20,-1,null,statenum_t.S_NULL,0,0),	// S_SPOS_XDIE9
    new state_t(spritenum_t.SPR_SPOS,11,5,null,statenum_t.S_SPOS_RAISE2,0,0),	// S_SPOS_RAISE1
    new state_t(spritenum_t.SPR_SPOS,10,5,null,statenum_t.S_SPOS_RAISE3,0,0),	// S_SPOS_RAISE2
    new state_t(spritenum_t.SPR_SPOS,9,5,null,statenum_t.S_SPOS_RAISE4,0,0),	// S_SPOS_RAISE3
    new state_t(spritenum_t.SPR_SPOS,8,5,null,statenum_t.S_SPOS_RAISE5,0,0),	// S_SPOS_RAISE4
    new state_t(spritenum_t.SPR_SPOS,7,5,null,statenum_t.S_SPOS_RUN1,0,0),	// S_SPOS_RAISE5
    new state_t(spritenum_t.SPR_VILE,0,10,think_t.A_Look,statenum_t.S_VILE_STND2,0,0),	// S_VILE_STND
    new state_t(spritenum_t.SPR_VILE,1,10,think_t.A_Look,statenum_t.S_VILE_STND,0,0),	// S_VILE_STND2
    new state_t(spritenum_t.SPR_VILE,0,2,think_t.A_VileChase,statenum_t.S_VILE_RUN2,0,0),	// S_VILE_RUN1
    new state_t(spritenum_t.SPR_VILE,0,2,think_t.A_VileChase,statenum_t.S_VILE_RUN3,0,0),	// S_VILE_RUN2
    new state_t(spritenum_t.SPR_VILE,1,2,think_t.A_VileChase,statenum_t.S_VILE_RUN4,0,0),	// S_VILE_RUN3
    new state_t(spritenum_t.SPR_VILE,1,2,think_t.A_VileChase,statenum_t.S_VILE_RUN5,0,0),	// S_VILE_RUN4
    new state_t(spritenum_t.SPR_VILE,2,2,think_t.A_VileChase,statenum_t.S_VILE_RUN6,0,0),	// S_VILE_RUN5
    new state_t(spritenum_t.SPR_VILE,2,2,think_t.A_VileChase,statenum_t.S_VILE_RUN7,0,0),	// S_VILE_RUN6
    new state_t(spritenum_t.SPR_VILE,3,2,think_t.A_VileChase,statenum_t.S_VILE_RUN8,0,0),	// S_VILE_RUN7
    new state_t(spritenum_t.SPR_VILE,3,2,think_t.A_VileChase,statenum_t.S_VILE_RUN9,0,0),	// S_VILE_RUN8
    new state_t(spritenum_t.SPR_VILE,4,2,think_t.A_VileChase,statenum_t.S_VILE_RUN10,0,0),	// S_VILE_RUN9
    new state_t(spritenum_t.SPR_VILE,4,2,think_t.A_VileChase,statenum_t.S_VILE_RUN11,0,0),	// S_VILE_RUN10
    new state_t(spritenum_t.SPR_VILE,5,2,think_t.A_VileChase,statenum_t.S_VILE_RUN12,0,0),	// S_VILE_RUN11
    new state_t(spritenum_t.SPR_VILE,5,2,think_t.A_VileChase,statenum_t.S_VILE_RUN1,0,0),	// S_VILE_RUN12
    new state_t(spritenum_t.SPR_VILE,32774,0,think_t.A_VileStart,statenum_t.S_VILE_ATK2,0,0),	// S_VILE_ATK1
    new state_t(spritenum_t.SPR_VILE,32774,10,think_t.A_FaceTarget,statenum_t.S_VILE_ATK3,0,0),	// S_VILE_ATK2
    new state_t(spritenum_t.SPR_VILE,32775,8,think_t.A_VileTarget,statenum_t.S_VILE_ATK4,0,0),	// S_VILE_ATK3
    new state_t(spritenum_t.SPR_VILE,32776,8,think_t.A_FaceTarget,statenum_t.S_VILE_ATK5,0,0),	// S_VILE_ATK4
    new state_t(spritenum_t.SPR_VILE,32777,8,think_t.A_FaceTarget,statenum_t.S_VILE_ATK6,0,0),	// S_VILE_ATK5
    new state_t(spritenum_t.SPR_VILE,32778,8,think_t.A_FaceTarget,statenum_t.S_VILE_ATK7,0,0),	// S_VILE_ATK6
    new state_t(spritenum_t.SPR_VILE,32779,8,think_t.A_FaceTarget,statenum_t.S_VILE_ATK8,0,0),	// S_VILE_ATK7
    new state_t(spritenum_t.SPR_VILE,32780,8,think_t.A_FaceTarget,statenum_t.S_VILE_ATK9,0,0),	// S_VILE_ATK8
    new state_t(spritenum_t.SPR_VILE,32781,8,think_t.A_FaceTarget,statenum_t.S_VILE_ATK10,0,0),	// S_VILE_ATK9
    new state_t(spritenum_t.SPR_VILE,32782,8,think_t.A_VileAttack,statenum_t.S_VILE_ATK11,0,0),	// S_VILE_ATK10
    new state_t(spritenum_t.SPR_VILE,32783,20,null,statenum_t.S_VILE_RUN1,0,0),	// S_VILE_ATK11
    new state_t(spritenum_t.SPR_VILE,32794,10,null,statenum_t.S_VILE_HEAL2,0,0),	// S_VILE_HEAL1
    new state_t(spritenum_t.SPR_VILE,32795,10,null,statenum_t.S_VILE_HEAL3,0,0),	// S_VILE_HEAL2
    new state_t(spritenum_t.SPR_VILE,32796,10,null,statenum_t.S_VILE_RUN1,0,0),	// S_VILE_HEAL3
    new state_t(spritenum_t.SPR_VILE,16,5,null,statenum_t.S_VILE_PAIN2,0,0),	// S_VILE_PAIN
    new state_t(spritenum_t.SPR_VILE,16,5,think_t.A_Pain,statenum_t.S_VILE_RUN1,0,0),	// S_VILE_PAIN2
    new state_t(spritenum_t.SPR_VILE,16,7,null,statenum_t.S_VILE_DIE2,0,0),	// S_VILE_DIE1
    new state_t(spritenum_t.SPR_VILE,17,7,think_t.A_Scream,statenum_t.S_VILE_DIE3,0,0),	// S_VILE_DIE2
    new state_t(spritenum_t.SPR_VILE,18,7,think_t.A_Fall,statenum_t.S_VILE_DIE4,0,0),	// S_VILE_DIE3
    new state_t(spritenum_t.SPR_VILE,19,7,null,statenum_t.S_VILE_DIE5,0,0),	// S_VILE_DIE4
    new state_t(spritenum_t.SPR_VILE,20,7,null,statenum_t.S_VILE_DIE6,0,0),	// S_VILE_DIE5
    new state_t(spritenum_t.SPR_VILE,21,7,null,statenum_t.S_VILE_DIE7,0,0),	// S_VILE_DIE6
    new state_t(spritenum_t.SPR_VILE,22,7,null,statenum_t.S_VILE_DIE8,0,0),	// S_VILE_DIE7
    new state_t(spritenum_t.SPR_VILE,23,5,null,statenum_t.S_VILE_DIE9,0,0),	// S_VILE_DIE8
    new state_t(spritenum_t.SPR_VILE,24,5,null,statenum_t.S_VILE_DIE10,0,0),	// S_VILE_DIE9
    new state_t(spritenum_t.SPR_VILE,25,-1,null,statenum_t.S_NULL,0,0),	// S_VILE_DIE10
    new state_t(spritenum_t.SPR_FIRE,32768,2,think_t.A_StartFire,statenum_t.S_FIRE2,0,0),	// S_FIRE1
    new state_t(spritenum_t.SPR_FIRE,32769,2,think_t.A_Fire,statenum_t.S_FIRE3,0,0),	// S_FIRE2
    new state_t(spritenum_t.SPR_FIRE,32768,2,think_t.A_Fire,statenum_t.S_FIRE4,0,0),	// S_FIRE3
    new state_t(spritenum_t.SPR_FIRE,32769,2,think_t.A_Fire,statenum_t.S_FIRE5,0,0),	// S_FIRE4
    new state_t(spritenum_t.SPR_FIRE,32770,2,think_t.A_FireCrackle,statenum_t.S_FIRE6,0,0),	// S_FIRE5
    new state_t(spritenum_t.SPR_FIRE,32769,2,think_t.A_Fire,statenum_t.S_FIRE7,0,0),	// S_FIRE6
    new state_t(spritenum_t.SPR_FIRE,32770,2,think_t.A_Fire,statenum_t.S_FIRE8,0,0),	// S_FIRE7
    new state_t(spritenum_t.SPR_FIRE,32769,2,think_t.A_Fire,statenum_t.S_FIRE9,0,0),	// S_FIRE8
    new state_t(spritenum_t.SPR_FIRE,32770,2,think_t.A_Fire,statenum_t.S_FIRE10,0,0),	// S_FIRE9
    new state_t(spritenum_t.SPR_FIRE,32771,2,think_t.A_Fire,statenum_t.S_FIRE11,0,0),	// S_FIRE10
    new state_t(spritenum_t.SPR_FIRE,32770,2,think_t.A_Fire,statenum_t.S_FIRE12,0,0),	// S_FIRE11
    new state_t(spritenum_t.SPR_FIRE,32771,2,think_t.A_Fire,statenum_t.S_FIRE13,0,0),	// S_FIRE12
    new state_t(spritenum_t.SPR_FIRE,32770,2,think_t.A_Fire,statenum_t.S_FIRE14,0,0),	// S_FIRE13
    new state_t(spritenum_t.SPR_FIRE,32771,2,think_t.A_Fire,statenum_t.S_FIRE15,0,0),	// S_FIRE14
    new state_t(spritenum_t.SPR_FIRE,32772,2,think_t.A_Fire,statenum_t.S_FIRE16,0,0),	// S_FIRE15
    new state_t(spritenum_t.SPR_FIRE,32771,2,think_t.A_Fire,statenum_t.S_FIRE17,0,0),	// S_FIRE16
    new state_t(spritenum_t.SPR_FIRE,32772,2,think_t.A_Fire,statenum_t.S_FIRE18,0,0),	// S_FIRE17
    new state_t(spritenum_t.SPR_FIRE,32771,2,think_t.A_Fire,statenum_t.S_FIRE19,0,0),	// S_FIRE18
    new state_t(spritenum_t.SPR_FIRE,32772,2,think_t.A_FireCrackle,statenum_t.S_FIRE20,0,0),	// S_FIRE19
    new state_t(spritenum_t.SPR_FIRE,32773,2,think_t.A_Fire,statenum_t.S_FIRE21,0,0),	// S_FIRE20
    new state_t(spritenum_t.SPR_FIRE,32772,2,think_t.A_Fire,statenum_t.S_FIRE22,0,0),	// S_FIRE21
    new state_t(spritenum_t.SPR_FIRE,32773,2,think_t.A_Fire,statenum_t.S_FIRE23,0,0),	// S_FIRE22
    new state_t(spritenum_t.SPR_FIRE,32772,2,think_t.A_Fire,statenum_t.S_FIRE24,0,0),	// S_FIRE23
    new state_t(spritenum_t.SPR_FIRE,32773,2,think_t.A_Fire,statenum_t.S_FIRE25,0,0),	// S_FIRE24
    new state_t(spritenum_t.SPR_FIRE,32774,2,think_t.A_Fire,statenum_t.S_FIRE26,0,0),	// S_FIRE25
    new state_t(spritenum_t.SPR_FIRE,32775,2,think_t.A_Fire,statenum_t.S_FIRE27,0,0),	// S_FIRE26
    new state_t(spritenum_t.SPR_FIRE,32774,2,think_t.A_Fire,statenum_t.S_FIRE28,0,0),	// S_FIRE27
    new state_t(spritenum_t.SPR_FIRE,32775,2,think_t.A_Fire,statenum_t.S_FIRE29,0,0),	// S_FIRE28
    new state_t(spritenum_t.SPR_FIRE,32774,2,think_t.A_Fire,statenum_t.S_FIRE30,0,0),	// S_FIRE29
    new state_t(spritenum_t.SPR_FIRE,32775,2,think_t.A_Fire,statenum_t.S_NULL,0,0),	// S_FIRE30
    new state_t(spritenum_t.SPR_PUFF,1,4,null,statenum_t.S_SMOKE2,0,0),	// S_SMOKE1
    new state_t(spritenum_t.SPR_PUFF,2,4,null,statenum_t.S_SMOKE3,0,0),	// S_SMOKE2
    new state_t(spritenum_t.SPR_PUFF,1,4,null,statenum_t.S_SMOKE4,0,0),	// S_SMOKE3
    new state_t(spritenum_t.SPR_PUFF,2,4,null,statenum_t.S_SMOKE5,0,0),	// S_SMOKE4
    new state_t(spritenum_t.SPR_PUFF,3,4,null,statenum_t.S_NULL,0,0),	// S_SMOKE5
    new state_t(spritenum_t.SPR_FATB,32768,2,think_t.A_Tracer,statenum_t.S_TRACER2,0,0),	// S_TRACER
    new state_t(spritenum_t.SPR_FATB,32769,2,think_t.A_Tracer,statenum_t.S_TRACER,0,0),	// S_TRACER2
    new state_t(spritenum_t.SPR_FBXP,32768,8,null,statenum_t.S_TRACEEXP2,0,0),	// S_TRACEEXP1
    new state_t(spritenum_t.SPR_FBXP,32769,6,null,statenum_t.S_TRACEEXP3,0,0),	// S_TRACEEXP2
    new state_t(spritenum_t.SPR_FBXP,32770,4,null,statenum_t.S_NULL,0,0),	// S_TRACEEXP3
    new state_t(spritenum_t.SPR_SKEL,0,10,think_t.A_Look,statenum_t.S_SKEL_STND2,0,0),	// S_SKEL_STND
    new state_t(spritenum_t.SPR_SKEL,1,10,think_t.A_Look,statenum_t.S_SKEL_STND,0,0),	// S_SKEL_STND2
    new state_t(spritenum_t.SPR_SKEL,0,2,think_t.A_Chase,statenum_t.S_SKEL_RUN2,0,0),	// S_SKEL_RUN1
    new state_t(spritenum_t.SPR_SKEL,0,2,think_t.A_Chase,statenum_t.S_SKEL_RUN3,0,0),	// S_SKEL_RUN2
    new state_t(spritenum_t.SPR_SKEL,1,2,think_t.A_Chase,statenum_t.S_SKEL_RUN4,0,0),	// S_SKEL_RUN3
    new state_t(spritenum_t.SPR_SKEL,1,2,think_t.A_Chase,statenum_t.S_SKEL_RUN5,0,0),	// S_SKEL_RUN4
    new state_t(spritenum_t.SPR_SKEL,2,2,think_t.A_Chase,statenum_t.S_SKEL_RUN6,0,0),	// S_SKEL_RUN5
    new state_t(spritenum_t.SPR_SKEL,2,2,think_t.A_Chase,statenum_t.S_SKEL_RUN7,0,0),	// S_SKEL_RUN6
    new state_t(spritenum_t.SPR_SKEL,3,2,think_t.A_Chase,statenum_t.S_SKEL_RUN8,0,0),	// S_SKEL_RUN7
    new state_t(spritenum_t.SPR_SKEL,3,2,think_t.A_Chase,statenum_t.S_SKEL_RUN9,0,0),	// S_SKEL_RUN8
    new state_t(spritenum_t.SPR_SKEL,4,2,think_t.A_Chase,statenum_t.S_SKEL_RUN10,0,0),	// S_SKEL_RUN9
    new state_t(spritenum_t.SPR_SKEL,4,2,think_t.A_Chase,statenum_t.S_SKEL_RUN11,0,0),	// S_SKEL_RUN10
    new state_t(spritenum_t.SPR_SKEL,5,2,think_t.A_Chase,statenum_t.S_SKEL_RUN12,0,0),	// S_SKEL_RUN11
    new state_t(spritenum_t.SPR_SKEL,5,2,think_t.A_Chase,statenum_t.S_SKEL_RUN1,0,0),	// S_SKEL_RUN12
    new state_t(spritenum_t.SPR_SKEL,6,0,think_t.A_FaceTarget,statenum_t.S_SKEL_FIST2,0,0),	// S_SKEL_FIST1
    new state_t(spritenum_t.SPR_SKEL,6,6,think_t.A_SkelWhoosh,statenum_t.S_SKEL_FIST3,0,0),	// S_SKEL_FIST2
    new state_t(spritenum_t.SPR_SKEL,7,6,think_t.A_FaceTarget,statenum_t.S_SKEL_FIST4,0,0),	// S_SKEL_FIST3
    new state_t(spritenum_t.SPR_SKEL,8,6,think_t.A_SkelFist,statenum_t.S_SKEL_RUN1,0,0),	// S_SKEL_FIST4
    new state_t(spritenum_t.SPR_SKEL,32777,0,think_t.A_FaceTarget,statenum_t.S_SKEL_MISS2,0,0),	// S_SKEL_MISS1
    new state_t(spritenum_t.SPR_SKEL,32777,10,think_t.A_FaceTarget,statenum_t.S_SKEL_MISS3,0,0),	// S_SKEL_MISS2
    new state_t(spritenum_t.SPR_SKEL,10,10,think_t.A_SkelMissile,statenum_t.S_SKEL_MISS4,0,0),	// S_SKEL_MISS3
    new state_t(spritenum_t.SPR_SKEL,10,10,think_t.A_FaceTarget,statenum_t.S_SKEL_RUN1,0,0),	// S_SKEL_MISS4
    new state_t(spritenum_t.SPR_SKEL,11,5,null,statenum_t.S_SKEL_PAIN2,0,0),	// S_SKEL_PAIN
    new state_t(spritenum_t.SPR_SKEL,11,5,think_t.A_Pain,statenum_t.S_SKEL_RUN1,0,0),	// S_SKEL_PAIN2
    new state_t(spritenum_t.SPR_SKEL,11,7,null,statenum_t.S_SKEL_DIE2,0,0),	// S_SKEL_DIE1
    new state_t(spritenum_t.SPR_SKEL,12,7,null,statenum_t.S_SKEL_DIE3,0,0),	// S_SKEL_DIE2
    new state_t(spritenum_t.SPR_SKEL,13,7,think_t.A_Scream,statenum_t.S_SKEL_DIE4,0,0),	// S_SKEL_DIE3
    new state_t(spritenum_t.SPR_SKEL,14,7,think_t.A_Fall,statenum_t.S_SKEL_DIE5,0,0),	// S_SKEL_DIE4
    new state_t(spritenum_t.SPR_SKEL,15,7,null,statenum_t.S_SKEL_DIE6,0,0),	// S_SKEL_DIE5
    new state_t(spritenum_t.SPR_SKEL,16,-1,null,statenum_t.S_NULL,0,0),	// S_SKEL_DIE6
    new state_t(spritenum_t.SPR_SKEL,16,5,null,statenum_t.S_SKEL_RAISE2,0,0),	// S_SKEL_RAISE1
    new state_t(spritenum_t.SPR_SKEL,15,5,null,statenum_t.S_SKEL_RAISE3,0,0),	// S_SKEL_RAISE2
    new state_t(spritenum_t.SPR_SKEL,14,5,null,statenum_t.S_SKEL_RAISE4,0,0),	// S_SKEL_RAISE3
    new state_t(spritenum_t.SPR_SKEL,13,5,null,statenum_t.S_SKEL_RAISE5,0,0),	// S_SKEL_RAISE4
    new state_t(spritenum_t.SPR_SKEL,12,5,null,statenum_t.S_SKEL_RAISE6,0,0),	// S_SKEL_RAISE5
    new state_t(spritenum_t.SPR_SKEL,11,5,null,statenum_t.S_SKEL_RUN1,0,0),	// S_SKEL_RAISE6
    new state_t(spritenum_t.SPR_MANF,32768,4,null,statenum_t.S_FATSHOT2,0,0),	// S_FATSHOT1
    new state_t(spritenum_t.SPR_MANF,32769,4,null,statenum_t.S_FATSHOT1,0,0),	// S_FATSHOT2
    new state_t(spritenum_t.SPR_MISL,32769,8,null,statenum_t.S_FATSHOTX2,0,0),	// S_FATSHOTX1
    new state_t(spritenum_t.SPR_MISL,32770,6,null,statenum_t.S_FATSHOTX3,0,0),	// S_FATSHOTX2
    new state_t(spritenum_t.SPR_MISL,32771,4,null,statenum_t.S_NULL,0,0),	// S_FATSHOTX3
    new state_t(spritenum_t.SPR_FATT,0,15,think_t.A_Look,statenum_t.S_FATT_STND2,0,0),	// S_FATT_STND
    new state_t(spritenum_t.SPR_FATT,1,15,think_t.A_Look,statenum_t.S_FATT_STND,0,0),	// S_FATT_STND2
    new state_t(spritenum_t.SPR_FATT,0,4,think_t.A_Chase,statenum_t.S_FATT_RUN2,0,0),	// S_FATT_RUN1
    new state_t(spritenum_t.SPR_FATT,0,4,think_t.A_Chase,statenum_t.S_FATT_RUN3,0,0),	// S_FATT_RUN2
    new state_t(spritenum_t.SPR_FATT,1,4,think_t.A_Chase,statenum_t.S_FATT_RUN4,0,0),	// S_FATT_RUN3
    new state_t(spritenum_t.SPR_FATT,1,4,think_t.A_Chase,statenum_t.S_FATT_RUN5,0,0),	// S_FATT_RUN4
    new state_t(spritenum_t.SPR_FATT,2,4,think_t.A_Chase,statenum_t.S_FATT_RUN6,0,0),	// S_FATT_RUN5
    new state_t(spritenum_t.SPR_FATT,2,4,think_t.A_Chase,statenum_t.S_FATT_RUN7,0,0),	// S_FATT_RUN6
    new state_t(spritenum_t.SPR_FATT,3,4,think_t.A_Chase,statenum_t.S_FATT_RUN8,0,0),	// S_FATT_RUN7
    new state_t(spritenum_t.SPR_FATT,3,4,think_t.A_Chase,statenum_t.S_FATT_RUN9,0,0),	// S_FATT_RUN8
    new state_t(spritenum_t.SPR_FATT,4,4,think_t.A_Chase,statenum_t.S_FATT_RUN10,0,0),	// S_FATT_RUN9
    new state_t(spritenum_t.SPR_FATT,4,4,think_t.A_Chase,statenum_t.S_FATT_RUN11,0,0),	// S_FATT_RUN10
    new state_t(spritenum_t.SPR_FATT,5,4,think_t.A_Chase,statenum_t.S_FATT_RUN12,0,0),	// S_FATT_RUN11
    new state_t(spritenum_t.SPR_FATT,5,4,think_t.A_Chase,statenum_t.S_FATT_RUN1,0,0),	// S_FATT_RUN12
    new state_t(spritenum_t.SPR_FATT,6,20,think_t.A_FatRaise,statenum_t.S_FATT_ATK2,0,0),	// S_FATT_ATK1
    new state_t(spritenum_t.SPR_FATT,32775,10,think_t.A_FatAttack1,statenum_t.S_FATT_ATK3,0,0),	// S_FATT_ATK2
    new state_t(spritenum_t.SPR_FATT,8,5,think_t.A_FaceTarget,statenum_t.S_FATT_ATK4,0,0),	// S_FATT_ATK3
    new state_t(spritenum_t.SPR_FATT,6,5,think_t.A_FaceTarget,statenum_t.S_FATT_ATK5,0,0),	// S_FATT_ATK4
    new state_t(spritenum_t.SPR_FATT,32775,10,think_t.A_FatAttack2,statenum_t.S_FATT_ATK6,0,0),	// S_FATT_ATK5
    new state_t(spritenum_t.SPR_FATT,8,5,think_t.A_FaceTarget,statenum_t.S_FATT_ATK7,0,0),	// S_FATT_ATK6
    new state_t(spritenum_t.SPR_FATT,6,5,think_t.A_FaceTarget,statenum_t.S_FATT_ATK8,0,0),	// S_FATT_ATK7
    new state_t(spritenum_t.SPR_FATT,32775,10,think_t.A_FatAttack3,statenum_t.S_FATT_ATK9,0,0),	// S_FATT_ATK8
    new state_t(spritenum_t.SPR_FATT,8,5,think_t.A_FaceTarget,statenum_t.S_FATT_ATK10,0,0),	// S_FATT_ATK9
    new state_t(spritenum_t.SPR_FATT,6,5,think_t.A_FaceTarget,statenum_t.S_FATT_RUN1,0,0),	// S_FATT_ATK10
    new state_t(spritenum_t.SPR_FATT,9,3,null,statenum_t.S_FATT_PAIN2,0,0),	// S_FATT_PAIN
    new state_t(spritenum_t.SPR_FATT,9,3,think_t.A_Pain,statenum_t.S_FATT_RUN1,0,0),	// S_FATT_PAIN2
    new state_t(spritenum_t.SPR_FATT,10,6,null,statenum_t.S_FATT_DIE2,0,0),	// S_FATT_DIE1
    new state_t(spritenum_t.SPR_FATT,11,6,think_t.A_Scream,statenum_t.S_FATT_DIE3,0,0),	// S_FATT_DIE2
    new state_t(spritenum_t.SPR_FATT,12,6,think_t.A_Fall,statenum_t.S_FATT_DIE4,0,0),	// S_FATT_DIE3
    new state_t(spritenum_t.SPR_FATT,13,6,null,statenum_t.S_FATT_DIE5,0,0),	// S_FATT_DIE4
    new state_t(spritenum_t.SPR_FATT,14,6,null,statenum_t.S_FATT_DIE6,0,0),	// S_FATT_DIE5
    new state_t(spritenum_t.SPR_FATT,15,6,null,statenum_t.S_FATT_DIE7,0,0),	// S_FATT_DIE6
    new state_t(spritenum_t.SPR_FATT,16,6,null,statenum_t.S_FATT_DIE8,0,0),	// S_FATT_DIE7
    new state_t(spritenum_t.SPR_FATT,17,6,null,statenum_t.S_FATT_DIE9,0,0),	// S_FATT_DIE8
    new state_t(spritenum_t.SPR_FATT,18,6,null,statenum_t.S_FATT_DIE10,0,0),	// S_FATT_DIE9
    new state_t(spritenum_t.SPR_FATT,19,-1,think_t.A_BossDeath,statenum_t.S_NULL,0,0),	// S_FATT_DIE10
    new state_t(spritenum_t.SPR_FATT,17,5,null,statenum_t.S_FATT_RAISE2,0,0),	// S_FATT_RAISE1
    new state_t(spritenum_t.SPR_FATT,16,5,null,statenum_t.S_FATT_RAISE3,0,0),	// S_FATT_RAISE2
    new state_t(spritenum_t.SPR_FATT,15,5,null,statenum_t.S_FATT_RAISE4,0,0),	// S_FATT_RAISE3
    new state_t(spritenum_t.SPR_FATT,14,5,null,statenum_t.S_FATT_RAISE5,0,0),	// S_FATT_RAISE4
    new state_t(spritenum_t.SPR_FATT,13,5,null,statenum_t.S_FATT_RAISE6,0,0),	// S_FATT_RAISE5
    new state_t(spritenum_t.SPR_FATT,12,5,null,statenum_t.S_FATT_RAISE7,0,0),	// S_FATT_RAISE6
    new state_t(spritenum_t.SPR_FATT,11,5,null,statenum_t.S_FATT_RAISE8,0,0),	// S_FATT_RAISE7
    new state_t(spritenum_t.SPR_FATT,10,5,null,statenum_t.S_FATT_RUN1,0,0),	// S_FATT_RAISE8
    new state_t(spritenum_t.SPR_CPOS,0,10,think_t.A_Look,statenum_t.S_CPOS_STND2,0,0),	// S_CPOS_STND
    new state_t(spritenum_t.SPR_CPOS,1,10,think_t.A_Look,statenum_t.S_CPOS_STND,0,0),	// S_CPOS_STND2
    new state_t(spritenum_t.SPR_CPOS,0,3,think_t.A_Chase,statenum_t.S_CPOS_RUN2,0,0),	// S_CPOS_RUN1
    new state_t(spritenum_t.SPR_CPOS,0,3,think_t.A_Chase,statenum_t.S_CPOS_RUN3,0,0),	// S_CPOS_RUN2
    new state_t(spritenum_t.SPR_CPOS,1,3,think_t.A_Chase,statenum_t.S_CPOS_RUN4,0,0),	// S_CPOS_RUN3
    new state_t(spritenum_t.SPR_CPOS,1,3,think_t.A_Chase,statenum_t.S_CPOS_RUN5,0,0),	// S_CPOS_RUN4
    new state_t(spritenum_t.SPR_CPOS,2,3,think_t.A_Chase,statenum_t.S_CPOS_RUN6,0,0),	// S_CPOS_RUN5
    new state_t(spritenum_t.SPR_CPOS,2,3,think_t.A_Chase,statenum_t.S_CPOS_RUN7,0,0),	// S_CPOS_RUN6
    new state_t(spritenum_t.SPR_CPOS,3,3,think_t.A_Chase,statenum_t.S_CPOS_RUN8,0,0),	// S_CPOS_RUN7
    new state_t(spritenum_t.SPR_CPOS,3,3,think_t.A_Chase,statenum_t.S_CPOS_RUN1,0,0),	// S_CPOS_RUN8
    new state_t(spritenum_t.SPR_CPOS,4,10,think_t.A_FaceTarget,statenum_t.S_CPOS_ATK2,0,0),	// S_CPOS_ATK1
    new state_t(spritenum_t.SPR_CPOS,32773,4,think_t.A_CPosAttack,statenum_t.S_CPOS_ATK3,0,0),	// S_CPOS_ATK2
    new state_t(spritenum_t.SPR_CPOS,32772,4,think_t.A_CPosAttack,statenum_t.S_CPOS_ATK4,0,0),	// S_CPOS_ATK3
    new state_t(spritenum_t.SPR_CPOS,5,1,think_t.A_CPosRefire,statenum_t.S_CPOS_ATK2,0,0),	// S_CPOS_ATK4
    new state_t(spritenum_t.SPR_CPOS,6,3,null,statenum_t.S_CPOS_PAIN2,0,0),	// S_CPOS_PAIN
    new state_t(spritenum_t.SPR_CPOS,6,3,think_t.A_Pain,statenum_t.S_CPOS_RUN1,0,0),	// S_CPOS_PAIN2
    new state_t(spritenum_t.SPR_CPOS,7,5,null,statenum_t.S_CPOS_DIE2,0,0),	// S_CPOS_DIE1
    new state_t(spritenum_t.SPR_CPOS,8,5,think_t.A_Scream,statenum_t.S_CPOS_DIE3,0,0),	// S_CPOS_DIE2
    new state_t(spritenum_t.SPR_CPOS,9,5,think_t.A_Fall,statenum_t.S_CPOS_DIE4,0,0),	// S_CPOS_DIE3
    new state_t(spritenum_t.SPR_CPOS,10,5,null,statenum_t.S_CPOS_DIE5,0,0),	// S_CPOS_DIE4
    new state_t(spritenum_t.SPR_CPOS,11,5,null,statenum_t.S_CPOS_DIE6,0,0),	// S_CPOS_DIE5
    new state_t(spritenum_t.SPR_CPOS,12,5,null,statenum_t.S_CPOS_DIE7,0,0),	// S_CPOS_DIE6
    new state_t(spritenum_t.SPR_CPOS,13,-1,null,statenum_t.S_NULL,0,0),	// S_CPOS_DIE7
    new state_t(spritenum_t.SPR_CPOS,14,5,null,statenum_t.S_CPOS_XDIE2,0,0),	// S_CPOS_XDIE1
    new state_t(spritenum_t.SPR_CPOS,15,5,think_t.A_XScream,statenum_t.S_CPOS_XDIE3,0,0),	// S_CPOS_XDIE2
    new state_t(spritenum_t.SPR_CPOS,16,5,think_t.A_Fall,statenum_t.S_CPOS_XDIE4,0,0),	// S_CPOS_XDIE3
    new state_t(spritenum_t.SPR_CPOS,17,5,null,statenum_t.S_CPOS_XDIE5,0,0),	// S_CPOS_XDIE4
    new state_t(spritenum_t.SPR_CPOS,18,5,null,statenum_t.S_CPOS_XDIE6,0,0),	// S_CPOS_XDIE5
    new state_t(spritenum_t.SPR_CPOS,19,-1,null,statenum_t.S_NULL,0,0),	// S_CPOS_XDIE6
    new state_t(spritenum_t.SPR_CPOS,13,5,null,statenum_t.S_CPOS_RAISE2,0,0),	// S_CPOS_RAISE1
    new state_t(spritenum_t.SPR_CPOS,12,5,null,statenum_t.S_CPOS_RAISE3,0,0),	// S_CPOS_RAISE2
    new state_t(spritenum_t.SPR_CPOS,11,5,null,statenum_t.S_CPOS_RAISE4,0,0),	// S_CPOS_RAISE3
    new state_t(spritenum_t.SPR_CPOS,10,5,null,statenum_t.S_CPOS_RAISE5,0,0),	// S_CPOS_RAISE4
    new state_t(spritenum_t.SPR_CPOS,9,5,null,statenum_t.S_CPOS_RAISE6,0,0),	// S_CPOS_RAISE5
    new state_t(spritenum_t.SPR_CPOS,8,5,null,statenum_t.S_CPOS_RAISE7,0,0),	// S_CPOS_RAISE6
    new state_t(spritenum_t.SPR_CPOS,7,5,null,statenum_t.S_CPOS_RUN1,0,0),	// S_CPOS_RAISE7
    new state_t(spritenum_t.SPR_TROO,0,10,think_t.A_Look,statenum_t.S_TROO_STND2,0,0),	// S_TROO_STND
    new state_t(spritenum_t.SPR_TROO,1,10,think_t.A_Look,statenum_t.S_TROO_STND,0,0),	// S_TROO_STND2
    new state_t(spritenum_t.SPR_TROO,0,3,think_t.A_Chase,statenum_t.S_TROO_RUN2,0,0),	// S_TROO_RUN1
    new state_t(spritenum_t.SPR_TROO,0,3,think_t.A_Chase,statenum_t.S_TROO_RUN3,0,0),	// S_TROO_RUN2
    new state_t(spritenum_t.SPR_TROO,1,3,think_t.A_Chase,statenum_t.S_TROO_RUN4,0,0),	// S_TROO_RUN3
    new state_t(spritenum_t.SPR_TROO,1,3,think_t.A_Chase,statenum_t.S_TROO_RUN5,0,0),	// S_TROO_RUN4
    new state_t(spritenum_t.SPR_TROO,2,3,think_t.A_Chase,statenum_t.S_TROO_RUN6,0,0),	// S_TROO_RUN5
    new state_t(spritenum_t.SPR_TROO,2,3,think_t.A_Chase,statenum_t.S_TROO_RUN7,0,0),	// S_TROO_RUN6
    new state_t(spritenum_t.SPR_TROO,3,3,think_t.A_Chase,statenum_t.S_TROO_RUN8,0,0),	// S_TROO_RUN7
    new state_t(spritenum_t.SPR_TROO,3,3,think_t.A_Chase,statenum_t.S_TROO_RUN1,0,0),	// S_TROO_RUN8
    new state_t(spritenum_t.SPR_TROO,4,8,think_t.A_FaceTarget,statenum_t.S_TROO_ATK2,0,0),	// S_TROO_ATK1
    new state_t(spritenum_t.SPR_TROO,5,8,think_t.A_FaceTarget,statenum_t.S_TROO_ATK3,0,0),	// S_TROO_ATK2
    new state_t(spritenum_t.SPR_TROO,6,6,think_t.A_TroopAttack,statenum_t.S_TROO_RUN1,0,0),	// S_TROO_ATK3
    new state_t(spritenum_t.SPR_TROO,7,2,null,statenum_t.S_TROO_PAIN2,0,0),	// S_TROO_PAIN
    new state_t(spritenum_t.SPR_TROO,7,2,think_t.A_Pain,statenum_t.S_TROO_RUN1,0,0),	// S_TROO_PAIN2
    new state_t(spritenum_t.SPR_TROO,8,8,null,statenum_t.S_TROO_DIE2,0,0),	// S_TROO_DIE1
    new state_t(spritenum_t.SPR_TROO,9,8,think_t.A_Scream,statenum_t.S_TROO_DIE3,0,0),	// S_TROO_DIE2
    new state_t(spritenum_t.SPR_TROO,10,6,null,statenum_t.S_TROO_DIE4,0,0),	// S_TROO_DIE3
    new state_t(spritenum_t.SPR_TROO,11,6,think_t.A_Fall,statenum_t.S_TROO_DIE5,0,0),	// S_TROO_DIE4
    new state_t(spritenum_t.SPR_TROO,12,-1,null,statenum_t.S_NULL,0,0),	// S_TROO_DIE5
    new state_t(spritenum_t.SPR_TROO,13,5,null,statenum_t.S_TROO_XDIE2,0,0),	// S_TROO_XDIE1
    new state_t(spritenum_t.SPR_TROO,14,5,think_t.A_XScream,statenum_t.S_TROO_XDIE3,0,0),	// S_TROO_XDIE2
    new state_t(spritenum_t.SPR_TROO,15,5,null,statenum_t.S_TROO_XDIE4,0,0),	// S_TROO_XDIE3
    new state_t(spritenum_t.SPR_TROO,16,5,think_t.A_Fall,statenum_t.S_TROO_XDIE5,0,0),	// S_TROO_XDIE4
    new state_t(spritenum_t.SPR_TROO,17,5,null,statenum_t.S_TROO_XDIE6,0,0),	// S_TROO_XDIE5
    new state_t(spritenum_t.SPR_TROO,18,5,null,statenum_t.S_TROO_XDIE7,0,0),	// S_TROO_XDIE6
    new state_t(spritenum_t.SPR_TROO,19,5,null,statenum_t.S_TROO_XDIE8,0,0),	// S_TROO_XDIE7
    new state_t(spritenum_t.SPR_TROO,20,-1,null,statenum_t.S_NULL,0,0),	// S_TROO_XDIE8
    new state_t(spritenum_t.SPR_TROO,12,8,null,statenum_t.S_TROO_RAISE2,0,0),	// S_TROO_RAISE1
    new state_t(spritenum_t.SPR_TROO,11,8,null,statenum_t.S_TROO_RAISE3,0,0),	// S_TROO_RAISE2
    new state_t(spritenum_t.SPR_TROO,10,6,null,statenum_t.S_TROO_RAISE4,0,0),	// S_TROO_RAISE3
    new state_t(spritenum_t.SPR_TROO,9,6,null,statenum_t.S_TROO_RAISE5,0,0),	// S_TROO_RAISE4
    new state_t(spritenum_t.SPR_TROO,8,6,null,statenum_t.S_TROO_RUN1,0,0),	// S_TROO_RAISE5
    new state_t(spritenum_t.SPR_SARG,0,10,think_t.A_Look,statenum_t.S_SARG_STND2,0,0),	// S_SARG_STND
    new state_t(spritenum_t.SPR_SARG,1,10,think_t.A_Look,statenum_t.S_SARG_STND,0,0),	// S_SARG_STND2
    new state_t(spritenum_t.SPR_SARG,0,2,think_t.A_Chase,statenum_t.S_SARG_RUN2,0,0),	// S_SARG_RUN1
    new state_t(spritenum_t.SPR_SARG,0,2,think_t.A_Chase,statenum_t.S_SARG_RUN3,0,0),	// S_SARG_RUN2
    new state_t(spritenum_t.SPR_SARG,1,2,think_t.A_Chase,statenum_t.S_SARG_RUN4,0,0),	// S_SARG_RUN3
    new state_t(spritenum_t.SPR_SARG,1,2,think_t.A_Chase,statenum_t.S_SARG_RUN5,0,0),	// S_SARG_RUN4
    new state_t(spritenum_t.SPR_SARG,2,2,think_t.A_Chase,statenum_t.S_SARG_RUN6,0,0),	// S_SARG_RUN5
    new state_t(spritenum_t.SPR_SARG,2,2,think_t.A_Chase,statenum_t.S_SARG_RUN7,0,0),	// S_SARG_RUN6
    new state_t(spritenum_t.SPR_SARG,3,2,think_t.A_Chase,statenum_t.S_SARG_RUN8,0,0),	// S_SARG_RUN7
    new state_t(spritenum_t.SPR_SARG,3,2,think_t.A_Chase,statenum_t.S_SARG_RUN1,0,0),	// S_SARG_RUN8
    new state_t(spritenum_t.SPR_SARG,4,8,think_t.A_FaceTarget,statenum_t.S_SARG_ATK2,0,0),	// S_SARG_ATK1
    new state_t(spritenum_t.SPR_SARG,5,8,think_t.A_FaceTarget,statenum_t.S_SARG_ATK3,0,0),	// S_SARG_ATK2
    new state_t(spritenum_t.SPR_SARG,6,8,think_t.A_SargAttack,statenum_t.S_SARG_RUN1,0,0),	// S_SARG_ATK3
    new state_t(spritenum_t.SPR_SARG,7,2,null,statenum_t.S_SARG_PAIN2,0,0),	// S_SARG_PAIN
    new state_t(spritenum_t.SPR_SARG,7,2,think_t.A_Pain,statenum_t.S_SARG_RUN1,0,0),	// S_SARG_PAIN2
    new state_t(spritenum_t.SPR_SARG,8,8,null,statenum_t.S_SARG_DIE2,0,0),	// S_SARG_DIE1
    new state_t(spritenum_t.SPR_SARG,9,8,think_t.A_Scream,statenum_t.S_SARG_DIE3,0,0),	// S_SARG_DIE2
    new state_t(spritenum_t.SPR_SARG,10,4,null,statenum_t.S_SARG_DIE4,0,0),	// S_SARG_DIE3
    new state_t(spritenum_t.SPR_SARG,11,4,think_t.A_Fall,statenum_t.S_SARG_DIE5,0,0),	// S_SARG_DIE4
    new state_t(spritenum_t.SPR_SARG,12,4,null,statenum_t.S_SARG_DIE6,0,0),	// S_SARG_DIE5
    new state_t(spritenum_t.SPR_SARG,13,-1,null,statenum_t.S_NULL,0,0),	// S_SARG_DIE6
    new state_t(spritenum_t.SPR_SARG,13,5,null,statenum_t.S_SARG_RAISE2,0,0),	// S_SARG_RAISE1
    new state_t(spritenum_t.SPR_SARG,12,5,null,statenum_t.S_SARG_RAISE3,0,0),	// S_SARG_RAISE2
    new state_t(spritenum_t.SPR_SARG,11,5,null,statenum_t.S_SARG_RAISE4,0,0),	// S_SARG_RAISE3
    new state_t(spritenum_t.SPR_SARG,10,5,null,statenum_t.S_SARG_RAISE5,0,0),	// S_SARG_RAISE4
    new state_t(spritenum_t.SPR_SARG,9,5,null,statenum_t.S_SARG_RAISE6,0,0),	// S_SARG_RAISE5
    new state_t(spritenum_t.SPR_SARG,8,5,null,statenum_t.S_SARG_RUN1,0,0),	// S_SARG_RAISE6
    new state_t(spritenum_t.SPR_HEAD,0,10,think_t.A_Look,statenum_t.S_HEAD_STND,0,0),	// S_HEAD_STND
    new state_t(spritenum_t.SPR_HEAD,0,3,think_t.A_Chase,statenum_t.S_HEAD_RUN1,0,0),	// S_HEAD_RUN1
    new state_t(spritenum_t.SPR_HEAD,1,5,think_t.A_FaceTarget,statenum_t.S_HEAD_ATK2,0,0),	// S_HEAD_ATK1
    new state_t(spritenum_t.SPR_HEAD,2,5,think_t.A_FaceTarget,statenum_t.S_HEAD_ATK3,0,0),	// S_HEAD_ATK2
    new state_t(spritenum_t.SPR_HEAD,32771,5,think_t.A_HeadAttack,statenum_t.S_HEAD_RUN1,0,0),	// S_HEAD_ATK3
    new state_t(spritenum_t.SPR_HEAD,4,3,null,statenum_t.S_HEAD_PAIN2,0,0),	// S_HEAD_PAIN
    new state_t(spritenum_t.SPR_HEAD,4,3,think_t.A_Pain,statenum_t.S_HEAD_PAIN3,0,0),	// S_HEAD_PAIN2
    new state_t(spritenum_t.SPR_HEAD,5,6,null,statenum_t.S_HEAD_RUN1,0,0),	// S_HEAD_PAIN3
    new state_t(spritenum_t.SPR_HEAD,6,8,null,statenum_t.S_HEAD_DIE2,0,0),	// S_HEAD_DIE1
    new state_t(spritenum_t.SPR_HEAD,7,8,think_t.A_Scream,statenum_t.S_HEAD_DIE3,0,0),	// S_HEAD_DIE2
    new state_t(spritenum_t.SPR_HEAD,8,8,null,statenum_t.S_HEAD_DIE4,0,0),	// S_HEAD_DIE3
    new state_t(spritenum_t.SPR_HEAD,9,8,null,statenum_t.S_HEAD_DIE5,0,0),	// S_HEAD_DIE4
    new state_t(spritenum_t.SPR_HEAD,10,8,think_t.A_Fall,statenum_t.S_HEAD_DIE6,0,0),	// S_HEAD_DIE5
    new state_t(spritenum_t.SPR_HEAD,11,-1,null,statenum_t.S_NULL,0,0),	// S_HEAD_DIE6
    new state_t(spritenum_t.SPR_HEAD,11,8,null,statenum_t.S_HEAD_RAISE2,0,0),	// S_HEAD_RAISE1
    new state_t(spritenum_t.SPR_HEAD,10,8,null,statenum_t.S_HEAD_RAISE3,0,0),	// S_HEAD_RAISE2
    new state_t(spritenum_t.SPR_HEAD,9,8,null,statenum_t.S_HEAD_RAISE4,0,0),	// S_HEAD_RAISE3
    new state_t(spritenum_t.SPR_HEAD,8,8,null,statenum_t.S_HEAD_RAISE5,0,0),	// S_HEAD_RAISE4
    new state_t(spritenum_t.SPR_HEAD,7,8,null,statenum_t.S_HEAD_RAISE6,0,0),	// S_HEAD_RAISE5
    new state_t(spritenum_t.SPR_HEAD,6,8,null,statenum_t.S_HEAD_RUN1,0,0),	// S_HEAD_RAISE6
    new state_t(spritenum_t.SPR_BAL7,32768,4,null,statenum_t.S_BRBALL2,0,0),	// S_BRBALL1
    new state_t(spritenum_t.SPR_BAL7,32769,4,null,statenum_t.S_BRBALL1,0,0),	// S_BRBALL2
    new state_t(spritenum_t.SPR_BAL7,32770,6,null,statenum_t.S_BRBALLX2,0,0),	// S_BRBALLX1
    new state_t(spritenum_t.SPR_BAL7,32771,6,null,statenum_t.S_BRBALLX3,0,0),	// S_BRBALLX2
    new state_t(spritenum_t.SPR_BAL7,32772,6,null,statenum_t.S_NULL,0,0),	// S_BRBALLX3
    new state_t(spritenum_t.SPR_BOSS,0,10,think_t.A_Look,statenum_t.S_BOSS_STND2,0,0),	// S_BOSS_STND
    new state_t(spritenum_t.SPR_BOSS,1,10,think_t.A_Look,statenum_t.S_BOSS_STND,0,0),	// S_BOSS_STND2
    new state_t(spritenum_t.SPR_BOSS,0,3,think_t.A_Chase,statenum_t.S_BOSS_RUN2,0,0),	// S_BOSS_RUN1
    new state_t(spritenum_t.SPR_BOSS,0,3,think_t.A_Chase,statenum_t.S_BOSS_RUN3,0,0),	// S_BOSS_RUN2
    new state_t(spritenum_t.SPR_BOSS,1,3,think_t.A_Chase,statenum_t.S_BOSS_RUN4,0,0),	// S_BOSS_RUN3
    new state_t(spritenum_t.SPR_BOSS,1,3,think_t.A_Chase,statenum_t.S_BOSS_RUN5,0,0),	// S_BOSS_RUN4
    new state_t(spritenum_t.SPR_BOSS,2,3,think_t.A_Chase,statenum_t.S_BOSS_RUN6,0,0),	// S_BOSS_RUN5
    new state_t(spritenum_t.SPR_BOSS,2,3,think_t.A_Chase,statenum_t.S_BOSS_RUN7,0,0),	// S_BOSS_RUN6
    new state_t(spritenum_t.SPR_BOSS,3,3,think_t.A_Chase,statenum_t.S_BOSS_RUN8,0,0),	// S_BOSS_RUN7
    new state_t(spritenum_t.SPR_BOSS,3,3,think_t.A_Chase,statenum_t.S_BOSS_RUN1,0,0),	// S_BOSS_RUN8
    new state_t(spritenum_t.SPR_BOSS,4,8,think_t.A_FaceTarget,statenum_t.S_BOSS_ATK2,0,0),	// S_BOSS_ATK1
    new state_t(spritenum_t.SPR_BOSS,5,8,think_t.A_FaceTarget,statenum_t.S_BOSS_ATK3,0,0),	// S_BOSS_ATK2
    new state_t(spritenum_t.SPR_BOSS,6,8,think_t.A_BruisAttack,statenum_t.S_BOSS_RUN1,0,0),	// S_BOSS_ATK3
    new state_t(spritenum_t.SPR_BOSS,7,2,null,statenum_t.S_BOSS_PAIN2,0,0),	// S_BOSS_PAIN
    new state_t(spritenum_t.SPR_BOSS,7,2,think_t.A_Pain,statenum_t.S_BOSS_RUN1,0,0),	// S_BOSS_PAIN2
    new state_t(spritenum_t.SPR_BOSS,8,8,null,statenum_t.S_BOSS_DIE2,0,0),	// S_BOSS_DIE1
    new state_t(spritenum_t.SPR_BOSS,9,8,think_t.A_Scream,statenum_t.S_BOSS_DIE3,0,0),	// S_BOSS_DIE2
    new state_t(spritenum_t.SPR_BOSS,10,8,null,statenum_t.S_BOSS_DIE4,0,0),	// S_BOSS_DIE3
    new state_t(spritenum_t.SPR_BOSS,11,8,think_t.A_Fall,statenum_t.S_BOSS_DIE5,0,0),	// S_BOSS_DIE4
    new state_t(spritenum_t.SPR_BOSS,12,8,null,statenum_t.S_BOSS_DIE6,0,0),	// S_BOSS_DIE5
    new state_t(spritenum_t.SPR_BOSS,13,8,null,statenum_t.S_BOSS_DIE7,0,0),	// S_BOSS_DIE6
    new state_t(spritenum_t.SPR_BOSS,14,-1,think_t.A_BossDeath,statenum_t.S_NULL,0,0),	// S_BOSS_DIE7
    new state_t(spritenum_t.SPR_BOSS,14,8,null,statenum_t.S_BOSS_RAISE2,0,0),	// S_BOSS_RAISE1
    new state_t(spritenum_t.SPR_BOSS,13,8,null,statenum_t.S_BOSS_RAISE3,0,0),	// S_BOSS_RAISE2
    new state_t(spritenum_t.SPR_BOSS,12,8,null,statenum_t.S_BOSS_RAISE4,0,0),	// S_BOSS_RAISE3
    new state_t(spritenum_t.SPR_BOSS,11,8,null,statenum_t.S_BOSS_RAISE5,0,0),	// S_BOSS_RAISE4
    new state_t(spritenum_t.SPR_BOSS,10,8,null,statenum_t.S_BOSS_RAISE6,0,0),	// S_BOSS_RAISE5
    new state_t(spritenum_t.SPR_BOSS,9,8,null,statenum_t.S_BOSS_RAISE7,0,0),	// S_BOSS_RAISE6
    new state_t(spritenum_t.SPR_BOSS,8,8,null,statenum_t.S_BOSS_RUN1,0,0),	// S_BOSS_RAISE7
    new state_t(spritenum_t.SPR_BOS2,0,10,think_t.A_Look,statenum_t.S_BOS2_STND2,0,0),	// S_BOS2_STND
    new state_t(spritenum_t.SPR_BOS2,1,10,think_t.A_Look,statenum_t.S_BOS2_STND,0,0),	// S_BOS2_STND2
    new state_t(spritenum_t.SPR_BOS2,0,3,think_t.A_Chase,statenum_t.S_BOS2_RUN2,0,0),	// S_BOS2_RUN1
    new state_t(spritenum_t.SPR_BOS2,0,3,think_t.A_Chase,statenum_t.S_BOS2_RUN3,0,0),	// S_BOS2_RUN2
    new state_t(spritenum_t.SPR_BOS2,1,3,think_t.A_Chase,statenum_t.S_BOS2_RUN4,0,0),	// S_BOS2_RUN3
    new state_t(spritenum_t.SPR_BOS2,1,3,think_t.A_Chase,statenum_t.S_BOS2_RUN5,0,0),	// S_BOS2_RUN4
    new state_t(spritenum_t.SPR_BOS2,2,3,think_t.A_Chase,statenum_t.S_BOS2_RUN6,0,0),	// S_BOS2_RUN5
    new state_t(spritenum_t.SPR_BOS2,2,3,think_t.A_Chase,statenum_t.S_BOS2_RUN7,0,0),	// S_BOS2_RUN6
    new state_t(spritenum_t.SPR_BOS2,3,3,think_t.A_Chase,statenum_t.S_BOS2_RUN8,0,0),	// S_BOS2_RUN7
    new state_t(spritenum_t.SPR_BOS2,3,3,think_t.A_Chase,statenum_t.S_BOS2_RUN1,0,0),	// S_BOS2_RUN8
    new state_t(spritenum_t.SPR_BOS2,4,8,think_t.A_FaceTarget,statenum_t.S_BOS2_ATK2,0,0),	// S_BOS2_ATK1
    new state_t(spritenum_t.SPR_BOS2,5,8,think_t.A_FaceTarget,statenum_t.S_BOS2_ATK3,0,0),	// S_BOS2_ATK2
    new state_t(spritenum_t.SPR_BOS2,6,8,think_t.A_BruisAttack,statenum_t.S_BOS2_RUN1,0,0),	// S_BOS2_ATK3
    new state_t(spritenum_t.SPR_BOS2,7,2,null,statenum_t.S_BOS2_PAIN2,0,0),	// S_BOS2_PAIN
    new state_t(spritenum_t.SPR_BOS2,7,2,think_t.A_Pain,statenum_t.S_BOS2_RUN1,0,0),	// S_BOS2_PAIN2
    new state_t(spritenum_t.SPR_BOS2,8,8,null,statenum_t.S_BOS2_DIE2,0,0),	// S_BOS2_DIE1
    new state_t(spritenum_t.SPR_BOS2,9,8,think_t.A_Scream,statenum_t.S_BOS2_DIE3,0,0),	// S_BOS2_DIE2
    new state_t(spritenum_t.SPR_BOS2,10,8,null,statenum_t.S_BOS2_DIE4,0,0),	// S_BOS2_DIE3
    new state_t(spritenum_t.SPR_BOS2,11,8,think_t.A_Fall,statenum_t.S_BOS2_DIE5,0,0),	// S_BOS2_DIE4
    new state_t(spritenum_t.SPR_BOS2,12,8,null,statenum_t.S_BOS2_DIE6,0,0),	// S_BOS2_DIE5
    new state_t(spritenum_t.SPR_BOS2,13,8,null,statenum_t.S_BOS2_DIE7,0,0),	// S_BOS2_DIE6
    new state_t(spritenum_t.SPR_BOS2,14,-1,null,statenum_t.S_NULL,0,0),	// S_BOS2_DIE7
    new state_t(spritenum_t.SPR_BOS2,14,8,null,statenum_t.S_BOS2_RAISE2,0,0),	// S_BOS2_RAISE1
    new state_t(spritenum_t.SPR_BOS2,13,8,null,statenum_t.S_BOS2_RAISE3,0,0),	// S_BOS2_RAISE2
    new state_t(spritenum_t.SPR_BOS2,12,8,null,statenum_t.S_BOS2_RAISE4,0,0),	// S_BOS2_RAISE3
    new state_t(spritenum_t.SPR_BOS2,11,8,null,statenum_t.S_BOS2_RAISE5,0,0),	// S_BOS2_RAISE4
    new state_t(spritenum_t.SPR_BOS2,10,8,null,statenum_t.S_BOS2_RAISE6,0,0),	// S_BOS2_RAISE5
    new state_t(spritenum_t.SPR_BOS2,9,8,null,statenum_t.S_BOS2_RAISE7,0,0),	// S_BOS2_RAISE6
    new state_t(spritenum_t.SPR_BOS2,8,8,null,statenum_t.S_BOS2_RUN1,0,0),	// S_BOS2_RAISE7
    new state_t(spritenum_t.SPR_SKUL,32768,10,think_t.A_Look,statenum_t.S_SKULL_STND2,0,0),	// S_SKULL_STND
    new state_t(spritenum_t.SPR_SKUL,32769,10,think_t.A_Look,statenum_t.S_SKULL_STND,0,0),	// S_SKULL_STND2
    new state_t(spritenum_t.SPR_SKUL,32768,6,think_t.A_Chase,statenum_t.S_SKULL_RUN2,0,0),	// S_SKULL_RUN1
    new state_t(spritenum_t.SPR_SKUL,32769,6,think_t.A_Chase,statenum_t.S_SKULL_RUN1,0,0),	// S_SKULL_RUN2
    new state_t(spritenum_t.SPR_SKUL,32770,10,think_t.A_FaceTarget,statenum_t.S_SKULL_ATK2,0,0),	// S_SKULL_ATK1
    new state_t(spritenum_t.SPR_SKUL,32771,4,think_t.A_SkullAttack,statenum_t.S_SKULL_ATK3,0,0),	// S_SKULL_ATK2
    new state_t(spritenum_t.SPR_SKUL,32770,4,null,statenum_t.S_SKULL_ATK4,0,0),	// S_SKULL_ATK3
    new state_t(spritenum_t.SPR_SKUL,32771,4,null,statenum_t.S_SKULL_ATK3,0,0),	// S_SKULL_ATK4
    new state_t(spritenum_t.SPR_SKUL,32772,3,null,statenum_t.S_SKULL_PAIN2,0,0),	// S_SKULL_PAIN
    new state_t(spritenum_t.SPR_SKUL,32772,3,think_t.A_Pain,statenum_t.S_SKULL_RUN1,0,0),	// S_SKULL_PAIN2
    new state_t(spritenum_t.SPR_SKUL,32773,6,null,statenum_t.S_SKULL_DIE2,0,0),	// S_SKULL_DIE1
    new state_t(spritenum_t.SPR_SKUL,32774,6,think_t.A_Scream,statenum_t.S_SKULL_DIE3,0,0),	// S_SKULL_DIE2
    new state_t(spritenum_t.SPR_SKUL,32775,6,null,statenum_t.S_SKULL_DIE4,0,0),	// S_SKULL_DIE3
    new state_t(spritenum_t.SPR_SKUL,32776,6,think_t.A_Fall,statenum_t.S_SKULL_DIE5,0,0),	// S_SKULL_DIE4
    new state_t(spritenum_t.SPR_SKUL,9,6,null,statenum_t.S_SKULL_DIE6,0,0),	// S_SKULL_DIE5
    new state_t(spritenum_t.SPR_SKUL,10,6,null,statenum_t.S_NULL,0,0),	// S_SKULL_DIE6
    new state_t(spritenum_t.SPR_SPID,0,10,think_t.A_Look,statenum_t.S_SPID_STND2,0,0),	// S_SPID_STND
    new state_t(spritenum_t.SPR_SPID,1,10,think_t.A_Look,statenum_t.S_SPID_STND,0,0),	// S_SPID_STND2
    new state_t(spritenum_t.SPR_SPID,0,3,think_t.A_Metal,statenum_t.S_SPID_RUN2,0,0),	// S_SPID_RUN1
    new state_t(spritenum_t.SPR_SPID,0,3,think_t.A_Chase,statenum_t.S_SPID_RUN3,0,0),	// S_SPID_RUN2
    new state_t(spritenum_t.SPR_SPID,1,3,think_t.A_Chase,statenum_t.S_SPID_RUN4,0,0),	// S_SPID_RUN3
    new state_t(spritenum_t.SPR_SPID,1,3,think_t.A_Chase,statenum_t.S_SPID_RUN5,0,0),	// S_SPID_RUN4
    new state_t(spritenum_t.SPR_SPID,2,3,think_t.A_Metal,statenum_t.S_SPID_RUN6,0,0),	// S_SPID_RUN5
    new state_t(spritenum_t.SPR_SPID,2,3,think_t.A_Chase,statenum_t.S_SPID_RUN7,0,0),	// S_SPID_RUN6
    new state_t(spritenum_t.SPR_SPID,3,3,think_t.A_Chase,statenum_t.S_SPID_RUN8,0,0),	// S_SPID_RUN7
    new state_t(spritenum_t.SPR_SPID,3,3,think_t.A_Chase,statenum_t.S_SPID_RUN9,0,0),	// S_SPID_RUN8
    new state_t(spritenum_t.SPR_SPID,4,3,think_t.A_Metal,statenum_t.S_SPID_RUN10,0,0),	// S_SPID_RUN9
    new state_t(spritenum_t.SPR_SPID,4,3,think_t.A_Chase,statenum_t.S_SPID_RUN11,0,0),	// S_SPID_RUN10
    new state_t(spritenum_t.SPR_SPID,5,3,think_t.A_Chase,statenum_t.S_SPID_RUN12,0,0),	// S_SPID_RUN11
    new state_t(spritenum_t.SPR_SPID,5,3,think_t.A_Chase,statenum_t.S_SPID_RUN1,0,0),	// S_SPID_RUN12
    new state_t(spritenum_t.SPR_SPID,32768,20,think_t.A_FaceTarget,statenum_t.S_SPID_ATK2,0,0),	// S_SPID_ATK1
    new state_t(spritenum_t.SPR_SPID,32774,4,think_t.A_SPosAttack,statenum_t.S_SPID_ATK3,0,0),	// S_SPID_ATK2
    new state_t(spritenum_t.SPR_SPID,32775,4,think_t.A_SPosAttack,statenum_t.S_SPID_ATK4,0,0),	// S_SPID_ATK3
    new state_t(spritenum_t.SPR_SPID,32775,1,think_t.A_SpidRefire,statenum_t.S_SPID_ATK2,0,0),	// S_SPID_ATK4
    new state_t(spritenum_t.SPR_SPID,8,3,null,statenum_t.S_SPID_PAIN2,0,0),	// S_SPID_PAIN
    new state_t(spritenum_t.SPR_SPID,8,3,think_t.A_Pain,statenum_t.S_SPID_RUN1,0,0),	// S_SPID_PAIN2
    new state_t(spritenum_t.SPR_SPID,9,20,think_t.A_Scream,statenum_t.S_SPID_DIE2,0,0),	// S_SPID_DIE1
    new state_t(spritenum_t.SPR_SPID,10,10,think_t.A_Fall,statenum_t.S_SPID_DIE3,0,0),	// S_SPID_DIE2
    new state_t(spritenum_t.SPR_SPID,11,10,null,statenum_t.S_SPID_DIE4,0,0),	// S_SPID_DIE3
    new state_t(spritenum_t.SPR_SPID,12,10,null,statenum_t.S_SPID_DIE5,0,0),	// S_SPID_DIE4
    new state_t(spritenum_t.SPR_SPID,13,10,null,statenum_t.S_SPID_DIE6,0,0),	// S_SPID_DIE5
    new state_t(spritenum_t.SPR_SPID,14,10,null,statenum_t.S_SPID_DIE7,0,0),	// S_SPID_DIE6
    new state_t(spritenum_t.SPR_SPID,15,10,null,statenum_t.S_SPID_DIE8,0,0),	// S_SPID_DIE7
    new state_t(spritenum_t.SPR_SPID,16,10,null,statenum_t.S_SPID_DIE9,0,0),	// S_SPID_DIE8
    new state_t(spritenum_t.SPR_SPID,17,10,null,statenum_t.S_SPID_DIE10,0,0),	// S_SPID_DIE9
    new state_t(spritenum_t.SPR_SPID,18,30,null,statenum_t.S_SPID_DIE11,0,0),	// S_SPID_DIE10
    new state_t(spritenum_t.SPR_SPID,18,-1,think_t.A_BossDeath,statenum_t.S_NULL,0,0),	// S_SPID_DIE11
    new state_t(spritenum_t.SPR_BSPI,0,10,think_t.A_Look,statenum_t.S_BSPI_STND2,0,0),	// S_BSPI_STND
    new state_t(spritenum_t.SPR_BSPI,1,10,think_t.A_Look,statenum_t.S_BSPI_STND,0,0),	// S_BSPI_STND2
    new state_t(spritenum_t.SPR_BSPI,0,20,null,statenum_t.S_BSPI_RUN1,0,0),	// S_BSPI_SIGHT
    new state_t(spritenum_t.SPR_BSPI,0,3,think_t.A_BabyMetal,statenum_t.S_BSPI_RUN2,0,0),	// S_BSPI_RUN1
    new state_t(spritenum_t.SPR_BSPI,0,3,think_t.A_Chase,statenum_t.S_BSPI_RUN3,0,0),	// S_BSPI_RUN2
    new state_t(spritenum_t.SPR_BSPI,1,3,think_t.A_Chase,statenum_t.S_BSPI_RUN4,0,0),	// S_BSPI_RUN3
    new state_t(spritenum_t.SPR_BSPI,1,3,think_t.A_Chase,statenum_t.S_BSPI_RUN5,0,0),	// S_BSPI_RUN4
    new state_t(spritenum_t.SPR_BSPI,2,3,think_t.A_Chase,statenum_t.S_BSPI_RUN6,0,0),	// S_BSPI_RUN5
    new state_t(spritenum_t.SPR_BSPI,2,3,think_t.A_Chase,statenum_t.S_BSPI_RUN7,0,0),	// S_BSPI_RUN6
    new state_t(spritenum_t.SPR_BSPI,3,3,think_t.A_BabyMetal,statenum_t.S_BSPI_RUN8,0,0),	// S_BSPI_RUN7
    new state_t(spritenum_t.SPR_BSPI,3,3,think_t.A_Chase,statenum_t.S_BSPI_RUN9,0,0),	// S_BSPI_RUN8
    new state_t(spritenum_t.SPR_BSPI,4,3,think_t.A_Chase,statenum_t.S_BSPI_RUN10,0,0),	// S_BSPI_RUN9
    new state_t(spritenum_t.SPR_BSPI,4,3,think_t.A_Chase,statenum_t.S_BSPI_RUN11,0,0),	// S_BSPI_RUN10
    new state_t(spritenum_t.SPR_BSPI,5,3,think_t.A_Chase,statenum_t.S_BSPI_RUN12,0,0),	// S_BSPI_RUN11
    new state_t(spritenum_t.SPR_BSPI,5,3,think_t.A_Chase,statenum_t.S_BSPI_RUN1,0,0),	// S_BSPI_RUN12
    new state_t(spritenum_t.SPR_BSPI,32768,20,think_t.A_FaceTarget,statenum_t.S_BSPI_ATK2,0,0),	// S_BSPI_ATK1
    new state_t(spritenum_t.SPR_BSPI,32774,4,think_t.A_BspiAttack,statenum_t.S_BSPI_ATK3,0,0),	// S_BSPI_ATK2
    new state_t(spritenum_t.SPR_BSPI,32775,4,null,statenum_t.S_BSPI_ATK4,0,0),	// S_BSPI_ATK3
    new state_t(spritenum_t.SPR_BSPI,32775,1,think_t.A_SpidRefire,statenum_t.S_BSPI_ATK2,0,0),	// S_BSPI_ATK4
    new state_t(spritenum_t.SPR_BSPI,8,3,null,statenum_t.S_BSPI_PAIN2,0,0),	// S_BSPI_PAIN
    new state_t(spritenum_t.SPR_BSPI,8,3,think_t.A_Pain,statenum_t.S_BSPI_RUN1,0,0),	// S_BSPI_PAIN2
    new state_t(spritenum_t.SPR_BSPI,9,20,think_t.A_Scream,statenum_t.S_BSPI_DIE2,0,0),	// S_BSPI_DIE1
    new state_t(spritenum_t.SPR_BSPI,10,7,think_t.A_Fall,statenum_t.S_BSPI_DIE3,0,0),	// S_BSPI_DIE2
    new state_t(spritenum_t.SPR_BSPI,11,7,null,statenum_t.S_BSPI_DIE4,0,0),	// S_BSPI_DIE3
    new state_t(spritenum_t.SPR_BSPI,12,7,null,statenum_t.S_BSPI_DIE5,0,0),	// S_BSPI_DIE4
    new state_t(spritenum_t.SPR_BSPI,13,7,null,statenum_t.S_BSPI_DIE6,0,0),	// S_BSPI_DIE5
    new state_t(spritenum_t.SPR_BSPI,14,7,null,statenum_t.S_BSPI_DIE7,0,0),	// S_BSPI_DIE6
    new state_t(spritenum_t.SPR_BSPI,15,-1,think_t.A_BossDeath,statenum_t.S_NULL,0,0),	// S_BSPI_DIE7
    new state_t(spritenum_t.SPR_BSPI,15,5,null,statenum_t.S_BSPI_RAISE2,0,0),	// S_BSPI_RAISE1
    new state_t(spritenum_t.SPR_BSPI,14,5,null,statenum_t.S_BSPI_RAISE3,0,0),	// S_BSPI_RAISE2
    new state_t(spritenum_t.SPR_BSPI,13,5,null,statenum_t.S_BSPI_RAISE4,0,0),	// S_BSPI_RAISE3
    new state_t(spritenum_t.SPR_BSPI,12,5,null,statenum_t.S_BSPI_RAISE5,0,0),	// S_BSPI_RAISE4
    new state_t(spritenum_t.SPR_BSPI,11,5,null,statenum_t.S_BSPI_RAISE6,0,0),	// S_BSPI_RAISE5
    new state_t(spritenum_t.SPR_BSPI,10,5,null,statenum_t.S_BSPI_RAISE7,0,0),	// S_BSPI_RAISE6
    new state_t(spritenum_t.SPR_BSPI,9,5,null,statenum_t.S_BSPI_RUN1,0,0),	// S_BSPI_RAISE7
    new state_t(spritenum_t.SPR_APLS,32768,5,null,statenum_t.S_ARACH_PLAZ2,0,0),	// S_ARACH_PLAZ
    new state_t(spritenum_t.SPR_APLS,32769,5,null,statenum_t.S_ARACH_PLAZ,0,0),	// S_ARACH_PLAZ2
    new state_t(spritenum_t.SPR_APBX,32768,5,null,statenum_t.S_ARACH_PLEX2,0,0),	// S_ARACH_PLEX
    new state_t(spritenum_t.SPR_APBX,32769,5,null,statenum_t.S_ARACH_PLEX3,0,0),	// S_ARACH_PLEX2
    new state_t(spritenum_t.SPR_APBX,32770,5,null,statenum_t.S_ARACH_PLEX4,0,0),	// S_ARACH_PLEX3
    new state_t(spritenum_t.SPR_APBX,32771,5,null,statenum_t.S_ARACH_PLEX5,0,0),	// S_ARACH_PLEX4
    new state_t(spritenum_t.SPR_APBX,32772,5,null,statenum_t.S_NULL,0,0),	// S_ARACH_PLEX5
    new state_t(spritenum_t.SPR_CYBR,0,10,think_t.A_Look,statenum_t.S_CYBER_STND2,0,0),	// S_CYBER_STND
    new state_t(spritenum_t.SPR_CYBR,1,10,think_t.A_Look,statenum_t.S_CYBER_STND,0,0),	// S_CYBER_STND2
    new state_t(spritenum_t.SPR_CYBR,0,3,think_t.A_Hoof,statenum_t.S_CYBER_RUN2,0,0),	// S_CYBER_RUN1
    new state_t(spritenum_t.SPR_CYBR,0,3,think_t.A_Chase,statenum_t.S_CYBER_RUN3,0,0),	// S_CYBER_RUN2
    new state_t(spritenum_t.SPR_CYBR,1,3,think_t.A_Chase,statenum_t.S_CYBER_RUN4,0,0),	// S_CYBER_RUN3
    new state_t(spritenum_t.SPR_CYBR,1,3,think_t.A_Chase,statenum_t.S_CYBER_RUN5,0,0),	// S_CYBER_RUN4
    new state_t(spritenum_t.SPR_CYBR,2,3,think_t.A_Chase,statenum_t.S_CYBER_RUN6,0,0),	// S_CYBER_RUN5
    new state_t(spritenum_t.SPR_CYBR,2,3,think_t.A_Chase,statenum_t.S_CYBER_RUN7,0,0),	// S_CYBER_RUN6
    new state_t(spritenum_t.SPR_CYBR,3,3,think_t.A_Metal,statenum_t.S_CYBER_RUN8,0,0),	// S_CYBER_RUN7
    new state_t(spritenum_t.SPR_CYBR,3,3,think_t.A_Chase,statenum_t.S_CYBER_RUN1,0,0),	// S_CYBER_RUN8
    new state_t(spritenum_t.SPR_CYBR,4,6,think_t.A_FaceTarget,statenum_t.S_CYBER_ATK2,0,0),	// S_CYBER_ATK1
    new state_t(spritenum_t.SPR_CYBR,5,12,think_t.A_CyberAttack,statenum_t.S_CYBER_ATK3,0,0),	// S_CYBER_ATK2
    new state_t(spritenum_t.SPR_CYBR,4,12,think_t.A_FaceTarget,statenum_t.S_CYBER_ATK4,0,0),	// S_CYBER_ATK3
    new state_t(spritenum_t.SPR_CYBR,5,12,think_t.A_CyberAttack,statenum_t.S_CYBER_ATK5,0,0),	// S_CYBER_ATK4
    new state_t(spritenum_t.SPR_CYBR,4,12,think_t.A_FaceTarget,statenum_t.S_CYBER_ATK6,0,0),	// S_CYBER_ATK5
    new state_t(spritenum_t.SPR_CYBR,5,12,think_t.A_CyberAttack,statenum_t.S_CYBER_RUN1,0,0),	// S_CYBER_ATK6
    new state_t(spritenum_t.SPR_CYBR,6,10,think_t.A_Pain,statenum_t.S_CYBER_RUN1,0,0),	// S_CYBER_PAIN
    new state_t(spritenum_t.SPR_CYBR,7,10,null,statenum_t.S_CYBER_DIE2,0,0),	// S_CYBER_DIE1
    new state_t(spritenum_t.SPR_CYBR,8,10,think_t.A_Scream,statenum_t.S_CYBER_DIE3,0,0),	// S_CYBER_DIE2
    new state_t(spritenum_t.SPR_CYBR,9,10,null,statenum_t.S_CYBER_DIE4,0,0),	// S_CYBER_DIE3
    new state_t(spritenum_t.SPR_CYBR,10,10,null,statenum_t.S_CYBER_DIE5,0,0),	// S_CYBER_DIE4
    new state_t(spritenum_t.SPR_CYBR,11,10,null,statenum_t.S_CYBER_DIE6,0,0),	// S_CYBER_DIE5
    new state_t(spritenum_t.SPR_CYBR,12,10,think_t.A_Fall,statenum_t.S_CYBER_DIE7,0,0),	// S_CYBER_DIE6
    new state_t(spritenum_t.SPR_CYBR,13,10,null,statenum_t.S_CYBER_DIE8,0,0),	// S_CYBER_DIE7
    new state_t(spritenum_t.SPR_CYBR,14,10,null,statenum_t.S_CYBER_DIE9,0,0),	// S_CYBER_DIE8
    new state_t(spritenum_t.SPR_CYBR,15,30,null,statenum_t.S_CYBER_DIE10,0,0),	// S_CYBER_DIE9
    new state_t(spritenum_t.SPR_CYBR,15,-1,think_t.A_BossDeath,statenum_t.S_NULL,0,0),	// S_CYBER_DIE10
    new state_t(spritenum_t.SPR_PAIN,0,10,think_t.A_Look,statenum_t.S_PAIN_STND,0,0),	// S_PAIN_STND
    new state_t(spritenum_t.SPR_PAIN,0,3,think_t.A_Chase,statenum_t.S_PAIN_RUN2,0,0),	// S_PAIN_RUN1
    new state_t(spritenum_t.SPR_PAIN,0,3,think_t.A_Chase,statenum_t.S_PAIN_RUN3,0,0),	// S_PAIN_RUN2
    new state_t(spritenum_t.SPR_PAIN,1,3,think_t.A_Chase,statenum_t.S_PAIN_RUN4,0,0),	// S_PAIN_RUN3
    new state_t(spritenum_t.SPR_PAIN,1,3,think_t.A_Chase,statenum_t.S_PAIN_RUN5,0,0),	// S_PAIN_RUN4
    new state_t(spritenum_t.SPR_PAIN,2,3,think_t.A_Chase,statenum_t.S_PAIN_RUN6,0,0),	// S_PAIN_RUN5
    new state_t(spritenum_t.SPR_PAIN,2,3,think_t.A_Chase,statenum_t.S_PAIN_RUN1,0,0),	// S_PAIN_RUN6
    new state_t(spritenum_t.SPR_PAIN,3,5,think_t.A_FaceTarget,statenum_t.S_PAIN_ATK2,0,0),	// S_PAIN_ATK1
    new state_t(spritenum_t.SPR_PAIN,4,5,think_t.A_FaceTarget,statenum_t.S_PAIN_ATK3,0,0),	// S_PAIN_ATK2
    new state_t(spritenum_t.SPR_PAIN,32773,5,think_t.A_FaceTarget,statenum_t.S_PAIN_ATK4,0,0),	// S_PAIN_ATK3
    new state_t(spritenum_t.SPR_PAIN,32773,0,think_t.A_PainAttack,statenum_t.S_PAIN_RUN1,0,0),	// S_PAIN_ATK4
    new state_t(spritenum_t.SPR_PAIN,6,6,null,statenum_t.S_PAIN_PAIN2,0,0),	// S_PAIN_PAIN
    new state_t(spritenum_t.SPR_PAIN,6,6,think_t.A_Pain,statenum_t.S_PAIN_RUN1,0,0),	// S_PAIN_PAIN2
    new state_t(spritenum_t.SPR_PAIN,32775,8,null,statenum_t.S_PAIN_DIE2,0,0),	// S_PAIN_DIE1
    new state_t(spritenum_t.SPR_PAIN,32776,8,think_t.A_Scream,statenum_t.S_PAIN_DIE3,0,0),	// S_PAIN_DIE2
    new state_t(spritenum_t.SPR_PAIN,32777,8,null,statenum_t.S_PAIN_DIE4,0,0),	// S_PAIN_DIE3
    new state_t(spritenum_t.SPR_PAIN,32778,8,null,statenum_t.S_PAIN_DIE5,0,0),	// S_PAIN_DIE4
    new state_t(spritenum_t.SPR_PAIN,32779,8,think_t.A_PainDie,statenum_t.S_PAIN_DIE6,0,0),	// S_PAIN_DIE5
    new state_t(spritenum_t.SPR_PAIN,32780,8,null,statenum_t.S_NULL,0,0),	// S_PAIN_DIE6
    new state_t(spritenum_t.SPR_PAIN,12,8,null,statenum_t.S_PAIN_RAISE2,0,0),	// S_PAIN_RAISE1
    new state_t(spritenum_t.SPR_PAIN,11,8,null,statenum_t.S_PAIN_RAISE3,0,0),	// S_PAIN_RAISE2
    new state_t(spritenum_t.SPR_PAIN,10,8,null,statenum_t.S_PAIN_RAISE4,0,0),	// S_PAIN_RAISE3
    new state_t(spritenum_t.SPR_PAIN,9,8,null,statenum_t.S_PAIN_RAISE5,0,0),	// S_PAIN_RAISE4
    new state_t(spritenum_t.SPR_PAIN,8,8,null,statenum_t.S_PAIN_RAISE6,0,0),	// S_PAIN_RAISE5
    new state_t(spritenum_t.SPR_PAIN,7,8,null,statenum_t.S_PAIN_RUN1,0,0),	// S_PAIN_RAISE6
    new state_t(spritenum_t.SPR_SSWV,0,10,think_t.A_Look,statenum_t.S_SSWV_STND2,0,0),	// S_SSWV_STND
    new state_t(spritenum_t.SPR_SSWV,1,10,think_t.A_Look,statenum_t.S_SSWV_STND,0,0),	// S_SSWV_STND2
    new state_t(spritenum_t.SPR_SSWV,0,3,think_t.A_Chase,statenum_t.S_SSWV_RUN2,0,0),	// S_SSWV_RUN1
    new state_t(spritenum_t.SPR_SSWV,0,3,think_t.A_Chase,statenum_t.S_SSWV_RUN3,0,0),	// S_SSWV_RUN2
    new state_t(spritenum_t.SPR_SSWV,1,3,think_t.A_Chase,statenum_t.S_SSWV_RUN4,0,0),	// S_SSWV_RUN3
    new state_t(spritenum_t.SPR_SSWV,1,3,think_t.A_Chase,statenum_t.S_SSWV_RUN5,0,0),	// S_SSWV_RUN4
    new state_t(spritenum_t.SPR_SSWV,2,3,think_t.A_Chase,statenum_t.S_SSWV_RUN6,0,0),	// S_SSWV_RUN5
    new state_t(spritenum_t.SPR_SSWV,2,3,think_t.A_Chase,statenum_t.S_SSWV_RUN7,0,0),	// S_SSWV_RUN6
    new state_t(spritenum_t.SPR_SSWV,3,3,think_t.A_Chase,statenum_t.S_SSWV_RUN8,0,0),	// S_SSWV_RUN7
    new state_t(spritenum_t.SPR_SSWV,3,3,think_t.A_Chase,statenum_t.S_SSWV_RUN1,0,0),	// S_SSWV_RUN8
    new state_t(spritenum_t.SPR_SSWV,4,10,think_t.A_FaceTarget,statenum_t.S_SSWV_ATK2,0,0),	// S_SSWV_ATK1
    new state_t(spritenum_t.SPR_SSWV,5,10,think_t.A_FaceTarget,statenum_t.S_SSWV_ATK3,0,0),	// S_SSWV_ATK2
    new state_t(spritenum_t.SPR_SSWV,32774,4,think_t.A_CPosAttack,statenum_t.S_SSWV_ATK4,0,0),	// S_SSWV_ATK3
    new state_t(spritenum_t.SPR_SSWV,5,6,think_t.A_FaceTarget,statenum_t.S_SSWV_ATK5,0,0),	// S_SSWV_ATK4
    new state_t(spritenum_t.SPR_SSWV,32774,4,think_t.A_CPosAttack,statenum_t.S_SSWV_ATK6,0,0),	// S_SSWV_ATK5
    new state_t(spritenum_t.SPR_SSWV,5,1,think_t.A_CPosRefire,statenum_t.S_SSWV_ATK2,0,0),	// S_SSWV_ATK6
    new state_t(spritenum_t.SPR_SSWV,7,3,null,statenum_t.S_SSWV_PAIN2,0,0),	// S_SSWV_PAIN
    new state_t(spritenum_t.SPR_SSWV,7,3,think_t.A_Pain,statenum_t.S_SSWV_RUN1,0,0),	// S_SSWV_PAIN2
    new state_t(spritenum_t.SPR_SSWV,8,5,null,statenum_t.S_SSWV_DIE2,0,0),	// S_SSWV_DIE1
    new state_t(spritenum_t.SPR_SSWV,9,5,think_t.A_Scream,statenum_t.S_SSWV_DIE3,0,0),	// S_SSWV_DIE2
    new state_t(spritenum_t.SPR_SSWV,10,5,think_t.A_Fall,statenum_t.S_SSWV_DIE4,0,0),	// S_SSWV_DIE3
    new state_t(spritenum_t.SPR_SSWV,11,5,null,statenum_t.S_SSWV_DIE5,0,0),	// S_SSWV_DIE4
    new state_t(spritenum_t.SPR_SSWV,12,-1,null,statenum_t.S_NULL,0,0),	// S_SSWV_DIE5
    new state_t(spritenum_t.SPR_SSWV,13,5,null,statenum_t.S_SSWV_XDIE2,0,0),	// S_SSWV_XDIE1
    new state_t(spritenum_t.SPR_SSWV,14,5,think_t.A_XScream,statenum_t.S_SSWV_XDIE3,0,0),	// S_SSWV_XDIE2
    new state_t(spritenum_t.SPR_SSWV,15,5,think_t.A_Fall,statenum_t.S_SSWV_XDIE4,0,0),	// S_SSWV_XDIE3
    new state_t(spritenum_t.SPR_SSWV,16,5,null,statenum_t.S_SSWV_XDIE5,0,0),	// S_SSWV_XDIE4
    new state_t(spritenum_t.SPR_SSWV,17,5,null,statenum_t.S_SSWV_XDIE6,0,0),	// S_SSWV_XDIE5
    new state_t(spritenum_t.SPR_SSWV,18,5,null,statenum_t.S_SSWV_XDIE7,0,0),	// S_SSWV_XDIE6
    new state_t(spritenum_t.SPR_SSWV,19,5,null,statenum_t.S_SSWV_XDIE8,0,0),	// S_SSWV_XDIE7
    new state_t(spritenum_t.SPR_SSWV,20,5,null,statenum_t.S_SSWV_XDIE9,0,0),	// S_SSWV_XDIE8
    new state_t(spritenum_t.SPR_SSWV,21,-1,null,statenum_t.S_NULL,0,0),	// S_SSWV_XDIE9
    new state_t(spritenum_t.SPR_SSWV,12,5,null,statenum_t.S_SSWV_RAISE2,0,0),	// S_SSWV_RAISE1
    new state_t(spritenum_t.SPR_SSWV,11,5,null,statenum_t.S_SSWV_RAISE3,0,0),	// S_SSWV_RAISE2
    new state_t(spritenum_t.SPR_SSWV,10,5,null,statenum_t.S_SSWV_RAISE4,0,0),	// S_SSWV_RAISE3
    new state_t(spritenum_t.SPR_SSWV,9,5,null,statenum_t.S_SSWV_RAISE5,0,0),	// S_SSWV_RAISE4
    new state_t(spritenum_t.SPR_SSWV,8,5,null,statenum_t.S_SSWV_RUN1,0,0),	// S_SSWV_RAISE5
    new state_t(spritenum_t.SPR_KEEN,0,-1,null,statenum_t.S_KEENSTND,0,0),	// S_KEENSTND
    new state_t(spritenum_t.SPR_KEEN,0,6,null,statenum_t.S_COMMKEEN2,0,0),	// S_COMMKEEN
    new state_t(spritenum_t.SPR_KEEN,1,6,null,statenum_t.S_COMMKEEN3,0,0),	// S_COMMKEEN2
    new state_t(spritenum_t.SPR_KEEN,2,6,think_t.A_Scream,statenum_t.S_COMMKEEN4,0,0),	// S_COMMKEEN3
    new state_t(spritenum_t.SPR_KEEN,3,6,null,statenum_t.S_COMMKEEN5,0,0),	// S_COMMKEEN4
    new state_t(spritenum_t.SPR_KEEN,4,6,null,statenum_t.S_COMMKEEN6,0,0),	// S_COMMKEEN5
    new state_t(spritenum_t.SPR_KEEN,5,6,null,statenum_t.S_COMMKEEN7,0,0),	// S_COMMKEEN6
    new state_t(spritenum_t.SPR_KEEN,6,6,null,statenum_t.S_COMMKEEN8,0,0),	// S_COMMKEEN7
    new state_t(spritenum_t.SPR_KEEN,7,6,null,statenum_t.S_COMMKEEN9,0,0),	// S_COMMKEEN8
    new state_t(spritenum_t.SPR_KEEN,8,6,null,statenum_t.S_COMMKEEN10,0,0),	// S_COMMKEEN9
    new state_t(spritenum_t.SPR_KEEN,9,6,null,statenum_t.S_COMMKEEN11,0,0),	// S_COMMKEEN10
    new state_t(spritenum_t.SPR_KEEN,10,6,think_t.A_KeenDie,statenum_t.S_COMMKEEN12,0,0),// S_COMMKEEN11
    new state_t(spritenum_t.SPR_KEEN,11,-1,null,statenum_t.S_NULL,0,0),		// S_COMMKEEN12
    new state_t(spritenum_t.SPR_KEEN,12,4,null,statenum_t.S_KEENPAIN2,0,0),	// S_KEENPAIN
    new state_t(spritenum_t.SPR_KEEN,12,8,think_t.A_Pain,statenum_t.S_KEENSTND,0,0),	// S_KEENPAIN2
    new state_t(spritenum_t.SPR_BBRN,0,-1,null,statenum_t.S_NULL,0,0),		// S_BRAIN
    new state_t(spritenum_t.SPR_BBRN,1,36,think_t.A_BrainPain,statenum_t.S_BRAIN,0,0),	// S_BRAIN_PAIN
    new state_t(spritenum_t.SPR_BBRN,0,100,think_t.A_BrainScream,statenum_t.S_BRAIN_DIE2,0,0),	// S_BRAIN_DIE1
    new state_t(spritenum_t.SPR_BBRN,0,10,null,statenum_t.S_BRAIN_DIE3,0,0),	// S_BRAIN_DIE2
    new state_t(spritenum_t.SPR_BBRN,0,10,null,statenum_t.S_BRAIN_DIE4,0,0),	// S_BRAIN_DIE3
    new state_t(spritenum_t.SPR_BBRN,0,-1,think_t.A_BrainDie,statenum_t.S_NULL,0,0),	// S_BRAIN_DIE4
    new state_t(spritenum_t.SPR_SSWV,0,10,think_t.A_Look,statenum_t.S_BRAINEYE,0,0),	// S_BRAINEYE
    new state_t(spritenum_t.SPR_SSWV,0,181,think_t.A_BrainAwake,statenum_t.S_BRAINEYE1,0,0),	// S_BRAINEYESEE
    new state_t(spritenum_t.SPR_SSWV,0,150,think_t.A_BrainSpit,statenum_t.S_BRAINEYE1,0,0),	// S_BRAINEYE1
    new state_t(spritenum_t.SPR_BOSF,32768,3,think_t.A_SpawnSound,statenum_t.S_SPAWN2,0,0),	// S_SPAWN1
    new state_t(spritenum_t.SPR_BOSF,32769,3,think_t.A_SpawnFly,statenum_t.S_SPAWN3,0,0),	// S_SPAWN2
    new state_t(spritenum_t.SPR_BOSF,32770,3,think_t.A_SpawnFly,statenum_t.S_SPAWN4,0,0),	// S_SPAWN3
    new state_t(spritenum_t.SPR_BOSF,32771,3,think_t.A_SpawnFly,statenum_t.S_SPAWN1,0,0),	// S_SPAWN4
    new state_t(spritenum_t.SPR_FIRE,32768,4,think_t.A_Fire,statenum_t.S_SPAWNFIRE2,0,0),	// S_SPAWNFIRE1
    new state_t(spritenum_t.SPR_FIRE,32769,4,think_t.A_Fire,statenum_t.S_SPAWNFIRE3,0,0),	// S_SPAWNFIRE2
    new state_t(spritenum_t.SPR_FIRE,32770,4,think_t.A_Fire,statenum_t.S_SPAWNFIRE4,0,0),	// S_SPAWNFIRE3
    new state_t(spritenum_t.SPR_FIRE,32771,4,think_t.A_Fire,statenum_t.S_SPAWNFIRE5,0,0),	// S_SPAWNFIRE4
    new state_t(spritenum_t.SPR_FIRE,32772,4,think_t.A_Fire,statenum_t.S_SPAWNFIRE6,0,0),	// S_SPAWNFIRE5
    new state_t(spritenum_t.SPR_FIRE,32773,4,think_t.A_Fire,statenum_t.S_SPAWNFIRE7,0,0),	// S_SPAWNFIRE6
    new state_t(spritenum_t.SPR_FIRE,32774,4,think_t.A_Fire,statenum_t.S_SPAWNFIRE8,0,0),	// S_SPAWNFIRE7
    new state_t(spritenum_t.SPR_FIRE,32775,4,think_t.A_Fire,statenum_t.S_NULL,0,0),		// S_SPAWNFIRE8
    new state_t(spritenum_t.SPR_MISL,32769,10,null,statenum_t.S_BRAINEXPLODE2,0,0),	// S_BRAINEXPLODE1
    new state_t(spritenum_t.SPR_MISL,32770,10,null,statenum_t.S_BRAINEXPLODE3,0,0),	// S_BRAINEXPLODE2
    new state_t(spritenum_t.SPR_MISL,32771,10,think_t.A_BrainExplode,statenum_t.S_NULL,0,0),	// S_BRAINEXPLODE3
    new state_t(spritenum_t.SPR_ARM1,0,6,null,statenum_t.S_ARM1A,0,0),	// S_ARM1
    new state_t(spritenum_t.SPR_ARM1,32769,7,null,statenum_t.S_ARM1,0,0),	// S_ARM1A
    new state_t(spritenum_t.SPR_ARM2,0,6,null,statenum_t.S_ARM2A,0,0),	// S_ARM2
    new state_t(spritenum_t.SPR_ARM2,32769,6,null,statenum_t.S_ARM2,0,0),	// S_ARM2A
    new state_t(spritenum_t.SPR_BAR1,0,6,null,statenum_t.S_BAR2,0,0),	// S_BAR1
    new state_t(spritenum_t.SPR_BAR1,1,6,null,statenum_t.S_BAR1,0,0),	// S_BAR2
    new state_t(spritenum_t.SPR_BEXP,32768,5,null,statenum_t.S_BEXP2,0,0),	// S_BEXP
    new state_t(spritenum_t.SPR_BEXP,32769,5,think_t.A_Scream,statenum_t.S_BEXP3,0,0),	// S_BEXP2
    new state_t(spritenum_t.SPR_BEXP,32770,5,null,statenum_t.S_BEXP4,0,0),	// S_BEXP3
    new state_t(spritenum_t.SPR_BEXP,32771,10,think_t.A_Explode,statenum_t.S_BEXP5,0,0),	// S_BEXP4
    new state_t(spritenum_t.SPR_BEXP,32772,10,null,statenum_t.S_NULL,0,0),	// S_BEXP5
    new state_t(spritenum_t.SPR_FCAN,32768,4,null,statenum_t.S_BBAR2,0,0),	// S_BBAR1
    new state_t(spritenum_t.SPR_FCAN,32769,4,null,statenum_t.S_BBAR3,0,0),	// S_BBAR2
    new state_t(spritenum_t.SPR_FCAN,32770,4,null,statenum_t.S_BBAR1,0,0),	// S_BBAR3
    new state_t(spritenum_t.SPR_BON1,0,6,null,statenum_t.S_BON1A,0,0),	// S_BON1
    new state_t(spritenum_t.SPR_BON1,1,6,null,statenum_t.S_BON1B,0,0),	// S_BON1A
    new state_t(spritenum_t.SPR_BON1,2,6,null,statenum_t.S_BON1C,0,0),	// S_BON1B
    new state_t(spritenum_t.SPR_BON1,3,6,null,statenum_t.S_BON1D,0,0),	// S_BON1C
    new state_t(spritenum_t.SPR_BON1,2,6,null,statenum_t.S_BON1E,0,0),	// S_BON1D
    new state_t(spritenum_t.SPR_BON1,1,6,null,statenum_t.S_BON1,0,0),	// S_BON1E
    new state_t(spritenum_t.SPR_BON2,0,6,null,statenum_t.S_BON2A,0,0),	// S_BON2
    new state_t(spritenum_t.SPR_BON2,1,6,null,statenum_t.S_BON2B,0,0),	// S_BON2A
    new state_t(spritenum_t.SPR_BON2,2,6,null,statenum_t.S_BON2C,0,0),	// S_BON2B
    new state_t(spritenum_t.SPR_BON2,3,6,null,statenum_t.S_BON2D,0,0),	// S_BON2C
    new state_t(spritenum_t.SPR_BON2,2,6,null,statenum_t.S_BON2E,0,0),	// S_BON2D
    new state_t(spritenum_t.SPR_BON2,1,6,null,statenum_t.S_BON2,0,0),	// S_BON2E
    new state_t(spritenum_t.SPR_BKEY,0,10,null,statenum_t.S_BKEY2,0,0),	// S_BKEY
    new state_t(spritenum_t.SPR_BKEY,32769,10,null,statenum_t.S_BKEY,0,0),	// S_BKEY2
    new state_t(spritenum_t.SPR_RKEY,0,10,null,statenum_t.S_RKEY2,0,0),	// S_RKEY
    new state_t(spritenum_t.SPR_RKEY,32769,10,null,statenum_t.S_RKEY,0,0),	// S_RKEY2
    new state_t(spritenum_t.SPR_YKEY,0,10,null,statenum_t.S_YKEY2,0,0),	// S_YKEY
    new state_t(spritenum_t.SPR_YKEY,32769,10,null,statenum_t.S_YKEY,0,0),	// S_YKEY2
    new state_t(spritenum_t.SPR_BSKU,0,10,null,statenum_t.S_BSKULL2,0,0),	// S_BSKULL
    new state_t(spritenum_t.SPR_BSKU,32769,10,null,statenum_t.S_BSKULL,0,0),	// S_BSKULL2
    new state_t(spritenum_t.SPR_RSKU,0,10,null,statenum_t.S_RSKULL2,0,0),	// S_RSKULL
    new state_t(spritenum_t.SPR_RSKU,32769,10,null,statenum_t.S_RSKULL,0,0),	// S_RSKULL2
    new state_t(spritenum_t.SPR_YSKU,0,10,null,statenum_t.S_YSKULL2,0,0),	// S_YSKULL
    new state_t(spritenum_t.SPR_YSKU,32769,10,null,statenum_t.S_YSKULL,0,0),	// S_YSKULL2
    new state_t(spritenum_t.SPR_STIM,0,-1,null,statenum_t.S_NULL,0,0),	// S_STIM
    new state_t(spritenum_t.SPR_MEDI,0,-1,null,statenum_t.S_NULL,0,0),	// S_MEDI
    new state_t(spritenum_t.SPR_SOUL,32768,6,null,statenum_t.S_SOUL2,0,0),	// S_SOUL
    new state_t(spritenum_t.SPR_SOUL,32769,6,null,statenum_t.S_SOUL3,0,0),	// S_SOUL2
    new state_t(spritenum_t.SPR_SOUL,32770,6,null,statenum_t.S_SOUL4,0,0),	// S_SOUL3
    new state_t(spritenum_t.SPR_SOUL,32771,6,null,statenum_t.S_SOUL5,0,0),	// S_SOUL4
    new state_t(spritenum_t.SPR_SOUL,32770,6,null,statenum_t.S_SOUL6,0,0),	// S_SOUL5
    new state_t(spritenum_t.SPR_SOUL,32769,6,null,statenum_t.S_SOUL,0,0),	// S_SOUL6
    new state_t(spritenum_t.SPR_PINV,32768,6,null,statenum_t.S_PINV2,0,0),	// S_PINV
    new state_t(spritenum_t.SPR_PINV,32769,6,null,statenum_t.S_PINV3,0,0),	// S_PINV2
    new state_t(spritenum_t.SPR_PINV,32770,6,null,statenum_t.S_PINV4,0,0),	// S_PINV3
    new state_t(spritenum_t.SPR_PINV,32771,6,null,statenum_t.S_PINV,0,0),	// S_PINV4
    new state_t(spritenum_t.SPR_PSTR,32768,-1,null,statenum_t.S_NULL,0,0),	// S_PSTR
    new state_t(spritenum_t.SPR_PINS,32768,6,null,statenum_t.S_PINS2,0,0),	// S_PINS
    new state_t(spritenum_t.SPR_PINS,32769,6,null,statenum_t.S_PINS3,0,0),	// S_PINS2
    new state_t(spritenum_t.SPR_PINS,32770,6,null,statenum_t.S_PINS4,0,0),	// S_PINS3
    new state_t(spritenum_t.SPR_PINS,32771,6,null,statenum_t.S_PINS,0,0),	// S_PINS4
    new state_t(spritenum_t.SPR_MEGA,32768,6,null,statenum_t.S_MEGA2,0,0),	// S_MEGA
    new state_t(spritenum_t.SPR_MEGA,32769,6,null,statenum_t.S_MEGA3,0,0),	// S_MEGA2
    new state_t(spritenum_t.SPR_MEGA,32770,6,null,statenum_t.S_MEGA4,0,0),	// S_MEGA3
    new state_t(spritenum_t.SPR_MEGA,32771,6,null,statenum_t.S_MEGA,0,0),	// S_MEGA4
    new state_t(spritenum_t.SPR_SUIT,32768,-1,null,statenum_t.S_NULL,0,0),	// S_SUIT
    new state_t(spritenum_t.SPR_PMAP,32768,6,null,statenum_t.S_PMAP2,0,0),	// S_PMAP
    new state_t(spritenum_t.SPR_PMAP,32769,6,null,statenum_t.S_PMAP3,0,0),	// S_PMAP2
    new state_t(spritenum_t.SPR_PMAP,32770,6,null,statenum_t.S_PMAP4,0,0),	// S_PMAP3
    new state_t(spritenum_t.SPR_PMAP,32771,6,null,statenum_t.S_PMAP5,0,0),	// S_PMAP4
    new state_t(spritenum_t.SPR_PMAP,32770,6,null,statenum_t.S_PMAP6,0,0),	// S_PMAP5
    new state_t(spritenum_t.SPR_PMAP,32769,6,null,statenum_t.S_PMAP,0,0),	// S_PMAP6
    new state_t(spritenum_t.SPR_PVIS,32768,6,null,statenum_t.S_PVIS2,0,0),	// S_PVIS
    new state_t(spritenum_t.SPR_PVIS,1,6,null,statenum_t.S_PVIS,0,0),	// S_PVIS2
    new state_t(spritenum_t.SPR_CLIP,0,-1,null,statenum_t.S_NULL,0,0),	// S_CLIP
    new state_t(spritenum_t.SPR_AMMO,0,-1,null,statenum_t.S_NULL,0,0),	// S_AMMO
    new state_t(spritenum_t.SPR_ROCK,0,-1,null,statenum_t.S_NULL,0,0),	// S_ROCK
    new state_t(spritenum_t.SPR_BROK,0,-1,null,statenum_t.S_NULL,0,0),	// S_BROK
    new state_t(spritenum_t.SPR_CELL,0,-1,null,statenum_t.S_NULL,0,0),	// S_CELL
    new state_t(spritenum_t.SPR_CELP,0,-1,null,statenum_t.S_NULL,0,0),	// S_CELP
    new state_t(spritenum_t.SPR_SHEL,0,-1,null,statenum_t.S_NULL,0,0),	// S_SHEL
    new state_t(spritenum_t.SPR_SBOX,0,-1,null,statenum_t.S_NULL,0,0),	// S_SBOX
    new state_t(spritenum_t.SPR_BPAK,0,-1,null,statenum_t.S_NULL,0,0),	// S_BPAK
    new state_t(spritenum_t.SPR_BFUG,0,-1,null,statenum_t.S_NULL,0,0),	// S_BFUG
    new state_t(spritenum_t.SPR_MGUN,0,-1,null,statenum_t.S_NULL,0,0),	// S_MGUN
    new state_t(spritenum_t.SPR_CSAW,0,-1,null,statenum_t.S_NULL,0,0),	// S_CSAW
    new state_t(spritenum_t.SPR_LAUN,0,-1,null,statenum_t.S_NULL,0,0),	// S_LAUN
    new state_t(spritenum_t.SPR_PLAS,0,-1,null,statenum_t.S_NULL,0,0),	// S_PLAS
    new state_t(spritenum_t.SPR_SHOT,0,-1,null,statenum_t.S_NULL,0,0),	// S_SHOT
    new state_t(spritenum_t.SPR_SGN2,0,-1,null,statenum_t.S_NULL,0,0),	// S_SHOT2
    new state_t(spritenum_t.SPR_COLU,32768,-1,null,statenum_t.S_NULL,0,0),	// S_COLU
    new state_t(spritenum_t.SPR_SMT2,0,-1,null,statenum_t.S_NULL,0,0),	// S_STALAG
    new state_t(spritenum_t.SPR_GOR1,0,10,null,statenum_t.S_BLOODYTWITCH2,0,0),	// S_BLOODYTWITCH
    new state_t(spritenum_t.SPR_GOR1,1,15,null,statenum_t.S_BLOODYTWITCH3,0,0),	// S_BLOODYTWITCH2
    new state_t(spritenum_t.SPR_GOR1,2,8,null,statenum_t.S_BLOODYTWITCH4,0,0),	// S_BLOODYTWITCH3
    new state_t(spritenum_t.SPR_GOR1,1,6,null,statenum_t.S_BLOODYTWITCH,0,0),	// S_BLOODYTWITCH4
    new state_t(spritenum_t.SPR_PLAY,13,-1,null,statenum_t.S_NULL,0,0),	// S_DEADTORSO
    new state_t(spritenum_t.SPR_PLAY,18,-1,null,statenum_t.S_NULL,0,0),	// S_DEADBOTTOM
    new state_t(spritenum_t.SPR_POL2,0,-1,null,statenum_t.S_NULL,0,0),	// S_HEADSONSTICK
    new state_t(spritenum_t.SPR_POL5,0,-1,null,statenum_t.S_NULL,0,0),	// S_GIBS
    new state_t(spritenum_t.SPR_POL4,0,-1,null,statenum_t.S_NULL,0,0),	// S_HEADONASTICK
    new state_t(spritenum_t.SPR_POL3,32768,6,null,statenum_t.S_HEADCANDLES2,0,0),	// S_HEADCANDLES
    new state_t(spritenum_t.SPR_POL3,32769,6,null,statenum_t.S_HEADCANDLES,0,0),	// S_HEADCANDLES2
    new state_t(spritenum_t.SPR_POL1,0,-1,null,statenum_t.S_NULL,0,0),	// S_DEADSTICK
    new state_t(spritenum_t.SPR_POL6,0,6,null,statenum_t.S_LIVESTICK2,0,0),	// S_LIVESTICK
    new state_t(spritenum_t.SPR_POL6,1,8,null,statenum_t.S_LIVESTICK,0,0),	// S_LIVESTICK2
    new state_t(spritenum_t.SPR_GOR2,0,-1,null,statenum_t.S_NULL,0,0),	// S_MEAT2
    new state_t(spritenum_t.SPR_GOR3,0,-1,null,statenum_t.S_NULL,0,0),	// S_MEAT3
    new state_t(spritenum_t.SPR_GOR4,0,-1,null,statenum_t.S_NULL,0,0),	// S_MEAT4
    new state_t(spritenum_t.SPR_GOR5,0,-1,null,statenum_t.S_NULL,0,0),	// S_MEAT5
    new state_t(spritenum_t.SPR_SMIT,0,-1,null,statenum_t.S_NULL,0,0),	// S_STALAGTITE
    new state_t(spritenum_t.SPR_COL1,0,-1,null,statenum_t.S_NULL,0,0),	// S_TALLGRNCOL
    new state_t(spritenum_t.SPR_COL2,0,-1,null,statenum_t.S_NULL,0,0),	// S_SHRTGRNCOL
    new state_t(spritenum_t.SPR_COL3,0,-1,null,statenum_t.S_NULL,0,0),	// S_TALLREDCOL
    new state_t(spritenum_t.SPR_COL4,0,-1,null,statenum_t.S_NULL,0,0),	// S_SHRTREDCOL
    new state_t(spritenum_t.SPR_CAND,32768,-1,null,statenum_t.S_NULL,0,0),	// S_CANDLESTIK
    new state_t(spritenum_t.SPR_CBRA,32768,-1,null,statenum_t.S_NULL,0,0),	// S_CANDELABRA
    new state_t(spritenum_t.SPR_COL6,0,-1,null,statenum_t.S_NULL,0,0),	// S_SKULLCOL
    new state_t(spritenum_t.SPR_TRE1,0,-1,null,statenum_t.S_NULL,0,0),	// S_TORCHTREE
    new state_t(spritenum_t.SPR_TRE2,0,-1,null,statenum_t.S_NULL,0,0),	// S_BIGTREE
    new state_t(spritenum_t.SPR_ELEC,0,-1,null,statenum_t.S_NULL,0,0),	// S_TECHPILLAR
    new state_t(spritenum_t.SPR_CEYE,32768,6,null,statenum_t.S_EVILEYE2,0,0),	// S_EVILEYE
    new state_t(spritenum_t.SPR_CEYE,32769,6,null,statenum_t.S_EVILEYE3,0,0),	// S_EVILEYE2
    new state_t(spritenum_t.SPR_CEYE,32770,6,null,statenum_t.S_EVILEYE4,0,0),	// S_EVILEYE3
    new state_t(spritenum_t.SPR_CEYE,32769,6,null,statenum_t.S_EVILEYE,0,0),	// S_EVILEYE4
    new state_t(spritenum_t.SPR_FSKU,32768,6,null,statenum_t.S_FLOATSKULL2,0,0),	// S_FLOATSKULL
    new state_t(spritenum_t.SPR_FSKU,32769,6,null,statenum_t.S_FLOATSKULL3,0,0),	// S_FLOATSKULL2
    new state_t(spritenum_t.SPR_FSKU,32770,6,null,statenum_t.S_FLOATSKULL,0,0),	// S_FLOATSKULL3
    new state_t(spritenum_t.SPR_COL5,0,14,null,statenum_t.S_HEARTCOL2,0,0),	// S_HEARTCOL
    new state_t(spritenum_t.SPR_COL5,1,14,null,statenum_t.S_HEARTCOL,0,0),	// S_HEARTCOL2
    new state_t(spritenum_t.SPR_TBLU,32768,4,null,statenum_t.S_BLUETORCH2,0,0),	// S_BLUETORCH
    new state_t(spritenum_t.SPR_TBLU,32769,4,null,statenum_t.S_BLUETORCH3,0,0),	// S_BLUETORCH2
    new state_t(spritenum_t.SPR_TBLU,32770,4,null,statenum_t.S_BLUETORCH4,0,0),	// S_BLUETORCH3
    new state_t(spritenum_t.SPR_TBLU,32771,4,null,statenum_t.S_BLUETORCH,0,0),	// S_BLUETORCH4
    new state_t(spritenum_t.SPR_TGRN,32768,4,null,statenum_t.S_GREENTORCH2,0,0),	// S_GREENTORCH
    new state_t(spritenum_t.SPR_TGRN,32769,4,null,statenum_t.S_GREENTORCH3,0,0),	// S_GREENTORCH2
    new state_t(spritenum_t.SPR_TGRN,32770,4,null,statenum_t.S_GREENTORCH4,0,0),	// S_GREENTORCH3
    new state_t(spritenum_t.SPR_TGRN,32771,4,null,statenum_t.S_GREENTORCH,0,0),	// S_GREENTORCH4
    new state_t(spritenum_t.SPR_TRED,32768,4,null,statenum_t.S_REDTORCH2,0,0),	// S_REDTORCH
    new state_t(spritenum_t.SPR_TRED,32769,4,null,statenum_t.S_REDTORCH3,0,0),	// S_REDTORCH2
    new state_t(spritenum_t.SPR_TRED,32770,4,null,statenum_t.S_REDTORCH4,0,0),	// S_REDTORCH3
    new state_t(spritenum_t.SPR_TRED,32771,4,null,statenum_t.S_REDTORCH,0,0),	// S_REDTORCH4
    new state_t(spritenum_t.SPR_SMBT,32768,4,null,statenum_t.S_BTORCHSHRT2,0,0),	// S_BTORCHSHRT
    new state_t(spritenum_t.SPR_SMBT,32769,4,null,statenum_t.S_BTORCHSHRT3,0,0),	// S_BTORCHSHRT2
    new state_t(spritenum_t.SPR_SMBT,32770,4,null,statenum_t.S_BTORCHSHRT4,0,0),	// S_BTORCHSHRT3
    new state_t(spritenum_t.SPR_SMBT,32771,4,null,statenum_t.S_BTORCHSHRT,0,0),	// S_BTORCHSHRT4
    new state_t(spritenum_t.SPR_SMGT,32768,4,null,statenum_t.S_GTORCHSHRT2,0,0),	// S_GTORCHSHRT
    new state_t(spritenum_t.SPR_SMGT,32769,4,null,statenum_t.S_GTORCHSHRT3,0,0),	// S_GTORCHSHRT2
    new state_t(spritenum_t.SPR_SMGT,32770,4,null,statenum_t.S_GTORCHSHRT4,0,0),	// S_GTORCHSHRT3
    new state_t(spritenum_t.SPR_SMGT,32771,4,null,statenum_t.S_GTORCHSHRT,0,0),	// S_GTORCHSHRT4
    new state_t(spritenum_t.SPR_SMRT,32768,4,null,statenum_t.S_RTORCHSHRT2,0,0),	// S_RTORCHSHRT
    new state_t(spritenum_t.SPR_SMRT,32769,4,null,statenum_t.S_RTORCHSHRT3,0,0),	// S_RTORCHSHRT2
    new state_t(spritenum_t.SPR_SMRT,32770,4,null,statenum_t.S_RTORCHSHRT4,0,0),	// S_RTORCHSHRT3
    new state_t(spritenum_t.SPR_SMRT,32771,4,null,statenum_t.S_RTORCHSHRT,0,0),	// S_RTORCHSHRT4
    new state_t(spritenum_t.SPR_HDB1,0,-1,null,statenum_t.S_NULL,0,0),	// S_HANGNOGUTS
    new state_t(spritenum_t.SPR_HDB2,0,-1,null,statenum_t.S_NULL,0,0),	// S_HANGBNOBRAIN
    new state_t(spritenum_t.SPR_HDB3,0,-1,null,statenum_t.S_NULL,0,0),	// S_HANGTLOOKDN
    new state_t(spritenum_t.SPR_HDB4,0,-1,null,statenum_t.S_NULL,0,0),	// S_HANGTSKULL
    new state_t(spritenum_t.SPR_HDB5,0,-1,null,statenum_t.S_NULL,0,0),	// S_HANGTLOOKUP
    new state_t(spritenum_t.SPR_HDB6,0,-1,null,statenum_t.S_NULL,0,0),	// S_HANGTNOBRAIN
    new state_t(spritenum_t.SPR_POB1,0,-1,null,statenum_t.S_NULL,0,0),	// S_COLONGIBS
    new state_t(spritenum_t.SPR_POB2,0,-1,null,statenum_t.S_NULL,0,0),	// S_SMALLPOOL
    new state_t(spritenum_t.SPR_BRS1,0,-1,null,statenum_t.S_NULL,0,0),		// S_BRAINSTEM
    new state_t(spritenum_t.SPR_TLMP,32768,4,null,statenum_t.S_TECHLAMP2,0,0),	// S_TECHLAMP
    new state_t(spritenum_t.SPR_TLMP,32769,4,null,statenum_t.S_TECHLAMP3,0,0),	// S_TECHLAMP2
    new state_t(spritenum_t.SPR_TLMP,32770,4,null,statenum_t.S_TECHLAMP4,0,0),	// S_TECHLAMP3
    new state_t(spritenum_t.SPR_TLMP,32771,4,null,statenum_t.S_TECHLAMP,0,0),	// S_TECHLAMP4
    new state_t(spritenum_t.SPR_TLP2,32768,4,null,statenum_t.S_TECH2LAMP2,0,0),	// S_TECH2LAMP
    new state_t(spritenum_t.SPR_TLP2,32769,4,null,statenum_t.S_TECH2LAMP3,0,0),	// S_TECH2LAMP2
    new state_t(spritenum_t.SPR_TLP2,32770,4,null,statenum_t.S_TECH2LAMP4,0,0),	// S_TECH2LAMP3
    new state_t(spritenum_t.SPR_TLP2,32771,4,null,statenum_t.S_TECH2LAMP,0,0)	// S_TECH2LAMP4
};

public static mobjinfo_t[] mobjinfo = {
    new mobjinfo_t(		// MT_PLAYER
	-1,		// doomednum
	statenum_t.S_PLAY,		// spawnstate
	100,		// spawnhealth
	statenum_t.S_PLAY_RUN1,		// seestate
	sfxenum_t.sfx_None,		// seesound
	0,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_PLAY_PAIN,		// painstate
	255,		// painchance
	sfxenum_t.sfx_plpain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_PLAY_ATK1,		// missilestate
	statenum_t.S_PLAY_DIE1,		// deathstate
	statenum_t.S_PLAY_XDIE1,		// xdeathstate
	sfxenum_t.sfx_pldeth,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_POSSESSED
	3004,		// doomednum
	statenum_t.S_POSS_STND,		// spawnstate
	20,		// spawnhealth
	statenum_t.S_POSS_RUN1,		// seestate
	sfxenum_t.sfx_posit1,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_pistol,		// attacksound
	statenum_t.S_POSS_PAIN,		// painstate
	200,		// painchance
	sfxenum_t.sfx_popain,		// painsound
	statenum_t.S_NULL,		// meleestate MAES: BE careful with "0 - null" states!
	statenum_t.S_POSS_ATK1,		// missilestate
	statenum_t.S_POSS_DIE1,		// deathstate
	statenum_t.S_POSS_XDIE1,		// xdeathstate
	sfxenum_t.sfx_podth1,		// deathsound
	8,		// speed
	20*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_posact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_POSS_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_SHOTGUY
	9,		// doomednum
	statenum_t.S_SPOS_STND,		// spawnstate
	30,		// spawnhealth
	statenum_t.S_SPOS_RUN1,		// seestate
	sfxenum_t.sfx_posit2,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_shotgn,		// attacksound MAES: Weird, this was 0 :-S
	statenum_t.S_SPOS_PAIN,		// painstate
	170,		// painchance
	sfxenum_t.sfx_popain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_SPOS_ATK1,		// missilestate
	statenum_t.S_SPOS_DIE1,		// deathstate
	statenum_t.S_SPOS_XDIE1,		// xdeathstate
	sfxenum_t.sfx_podth2,		// deathsound
	8,		// speed
	20*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_posact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_SPOS_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_VILE
	64,		// doomednum
	statenum_t.S_VILE_STND,		// spawnstate
	700,		// spawnhealth
	statenum_t.S_VILE_RUN1,		// seestate
	sfxenum_t.sfx_vilsit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_VILE_PAIN,		// painstate
	10,		// painchance
	sfxenum_t.sfx_vipain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_VILE_ATK1,		// missilestate
	statenum_t.S_VILE_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_vildth,		// deathsound
	15,		// speed
	20*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	500,		// mass
	0,		// damage
	sfxenum_t.sfx_vilact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_FIRE
	-1,		// doomednum
	statenum_t.S_FIRE1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_UNDEAD
	66,		// doomednum
	statenum_t.S_SKEL_STND,		// spawnstate
	300,		// spawnhealth
	statenum_t.S_SKEL_RUN1,		// seestate
	sfxenum_t.sfx_skesit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_SKEL_PAIN,		// painstate
	100,		// painchance
	sfxenum_t.sfx_popain,		// painsound
	statenum_t.S_SKEL_FIST1,		// meleestate
	statenum_t.S_SKEL_MISS1,		// missilestate
	statenum_t.S_SKEL_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_skedth,		// deathsound
	10,		// speed
	20*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	500,		// mass
	0,		// damage
	sfxenum_t.sfx_skeact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_SKEL_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_TRACER
	-1,		// doomednum
	statenum_t.S_TRACER,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_skeatk,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_TRACEEXP1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_barexp,		// deathsound
	10*FRACUNIT,		// speed
	11*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	10,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_SMOKE
	-1,		// doomednum
	statenum_t.S_SMOKE1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_FATSO
	67,		// doomednum
	statenum_t.S_FATT_STND,		// spawnstate
	600,		// spawnhealth
	statenum_t.S_FATT_RUN1,		// seestate
	sfxenum_t.sfx_mansit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_FATT_PAIN,		// painstate
	80,		// painchance
	sfxenum_t.sfx_mnpain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_FATT_ATK1,		// missilestate
	statenum_t.S_FATT_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_mandth,		// deathsound
	8,		// speed
	48*FRACUNIT,		// radius
	64*FRACUNIT,		// height
	1000,		// mass
	0,		// damage
	sfxenum_t.sfx_posact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_FATT_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_FATSHOT
	-1,		// doomednum
	statenum_t.S_FATSHOT1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_firsht,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_FATSHOTX1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_firxpl,		// deathsound
	20*FRACUNIT,		// speed
	6*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	8,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_CHAINGUY
	65,		// doomednum
	statenum_t.S_CPOS_STND,		// spawnstate
	70,		// spawnhealth
	statenum_t.S_CPOS_RUN1,		// seestate
	sfxenum_t.sfx_posit2,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_CPOS_PAIN,		// painstate
	170,		// painchance
	sfxenum_t.sfx_popain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_CPOS_ATK1,		// missilestate
	statenum_t.S_CPOS_DIE1,		// deathstate
	statenum_t.S_CPOS_XDIE1,		// xdeathstate
	sfxenum_t.sfx_podth2,		// deathsound
	8,		// speed
	20*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_posact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_CPOS_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_TROOP
	3001,		// doomednum
	statenum_t.S_TROO_STND,		// spawnstate
	60,		// spawnhealth
	statenum_t.S_TROO_RUN1,		// seestate
	sfxenum_t.sfx_bgsit1,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_TROO_PAIN,		// painstate
	200,		// painchance
	sfxenum_t.sfx_popain,		// painsound
	statenum_t.S_TROO_ATK1,		// meleestate
	statenum_t.S_TROO_ATK1,		// missilestate
	statenum_t.S_TROO_DIE1,		// deathstate
	statenum_t.S_TROO_XDIE1,		// xdeathstate
	sfxenum_t.sfx_bgdth1,		// deathsound
	8,		// speed
	20*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_bgact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_TROO_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_SERGEANT
	3002,		// doomednum
	statenum_t.S_SARG_STND,		// spawnstate
	150,		// spawnhealth
	statenum_t.S_SARG_RUN1,		// seestate
	sfxenum_t.sfx_sgtsit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_sgtatk,		// attacksound
	statenum_t.S_SARG_PAIN,		// painstate
	180,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_SARG_ATK1,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_SARG_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_sgtdth,		// deathsound
	10,		// speed
	30*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	400,		// mass
	0,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_SARG_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_SHADOWS
	58,		// doomednum
	statenum_t.S_SARG_STND,		// spawnstate
	150,		// spawnhealth
	statenum_t.S_SARG_RUN1,		// seestate
	sfxenum_t.sfx_sgtsit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_sgtatk,		// attacksound
	statenum_t.S_SARG_PAIN,		// painstate
	180,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_SARG_ATK1,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_SARG_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_sgtdth,		// deathsound
	10,		// speed
	30*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	400,		// mass
	0,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_SHADOW|MF_COUNTKILL,		// flags
	statenum_t.S_SARG_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_HEAD
	3005,		// doomednum
	statenum_t.S_HEAD_STND,		// spawnstate
	400,		// spawnhealth
	statenum_t.S_HEAD_RUN1,		// seestate
	sfxenum_t.sfx_cacsit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_HEAD_PAIN,		// painstate
	128,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_HEAD_ATK1,		// missilestate
	statenum_t.S_HEAD_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_cacdth,		// deathsound
	8,		// speed
	31*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	400,		// mass
	0,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL,		// flags
	statenum_t.S_HEAD_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_BRUISER
	3003,		// doomednum
	statenum_t.S_BOSS_STND,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_BOSS_RUN1,		// seestate
	sfxenum_t.sfx_brssit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_BOSS_PAIN,		// painstate
	50,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_BOSS_ATK1,		// meleestate
	statenum_t.S_BOSS_ATK1,		// missilestate
	statenum_t.S_BOSS_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_brsdth,		// deathsound
	8,		// speed
	24*FRACUNIT,		// radius
	64*FRACUNIT,		// height
	1000,		// mass
	0,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_BOSS_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_BRUISERSHOT
	-1,		// doomednum
	statenum_t.S_BRBALL1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_firsht,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_BRBALLX1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_firxpl,		// deathsound
	15*FRACUNIT,		// speed
	6*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	8,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_KNIGHT
	69,		// doomednum
	statenum_t.S_BOS2_STND,		// spawnstate
	500,		// spawnhealth
	statenum_t.S_BOS2_RUN1,		// seestate
	sfxenum_t.sfx_kntsit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_BOS2_PAIN,		// painstate
	50,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_BOS2_ATK1,		// meleestate
	statenum_t.S_BOS2_ATK1,		// missilestate
	statenum_t.S_BOS2_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_kntdth,		// deathsound
	8,		// speed
	24*FRACUNIT,		// radius
	64*FRACUNIT,		// height
	1000,		// mass
	0,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_BOS2_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_SKULL
	3006,		// doomednum
	statenum_t.S_SKULL_STND,		// spawnstate
	100,		// spawnhealth
	statenum_t.S_SKULL_RUN1,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_sklatk,		// attacksound
	statenum_t.S_SKULL_PAIN,		// painstate
	256,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_SKULL_ATK1,		// missilestate
	statenum_t.S_SKULL_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_firxpl,		// deathsound
	8,		// speed
	16*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	50,		// mass
	3,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_SPIDER
	7,		// doomednum
	statenum_t.S_SPID_STND,		// spawnstate
	3000,		// spawnhealth
	statenum_t.S_SPID_RUN1,		// seestate
	sfxenum_t.sfx_spisit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_shotgn,		// attacksound
	statenum_t.S_SPID_PAIN,		// painstate
	40,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_SPID_ATK1,		// missilestate
	statenum_t.S_SPID_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_spidth,		// deathsound
	12,		// speed
	128*FRACUNIT,		// radius
	100*FRACUNIT,		// height
	1000,		// mass
	0,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_BABY
	68,		// doomednum
	statenum_t.S_BSPI_STND,		// spawnstate
	500,		// spawnhealth
	statenum_t.S_BSPI_SIGHT,		// seestate
	sfxenum_t.sfx_bspsit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_BSPI_PAIN,		// painstate
	128,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_BSPI_ATK1,		// missilestate
	statenum_t.S_BSPI_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_bspdth,		// deathsound
	12,		// speed
	64*FRACUNIT,		// radius
	64*FRACUNIT,		// height
	600,		// mass
	0,		// damage
	sfxenum_t.sfx_bspact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_BSPI_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_CYBORG
	16,		// doomednum
	statenum_t.S_CYBER_STND,		// spawnstate
	4000,		// spawnhealth
	statenum_t.S_CYBER_RUN1,		// seestate
	sfxenum_t.sfx_cybsit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_CYBER_PAIN,		// painstate
	20,		// painchance
	sfxenum_t.sfx_dmpain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_CYBER_ATK1,		// missilestate
	statenum_t.S_CYBER_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_cybdth,		// deathsound
	16,		// speed
	40*FRACUNIT,		// radius
	110*FRACUNIT,		// height
	1000,		// mass
	0,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_PAIN
	71,		// doomednum
	statenum_t.S_PAIN_STND,		// spawnstate
	400,		// spawnhealth
	statenum_t.S_PAIN_RUN1,		// seestate
	sfxenum_t.sfx_pesit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_PAIN_PAIN,		// painstate
	128,		// painchance
	sfxenum_t.sfx_pepain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_PAIN_ATK1,		// missilestate
	statenum_t.S_PAIN_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_pedth,		// deathsound
	8,		// speed
	31*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	400,		// mass
	0,		// damage
	sfxenum_t.sfx_dmact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL,		// flags
	statenum_t.S_PAIN_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_WOLFSS
	84,		// doomednum
	statenum_t.S_SSWV_STND,		// spawnstate
	50,		// spawnhealth
	statenum_t.S_SSWV_RUN1,		// seestate
	sfxenum_t.sfx_sssit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_SSWV_PAIN,		// painstate
	170,		// painchance
	sfxenum_t.sfx_popain,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_SSWV_ATK1,		// missilestate
	statenum_t.S_SSWV_DIE1,		// deathstate
	statenum_t.S_SSWV_XDIE1,		// xdeathstate
	sfxenum_t.sfx_ssdth,		// deathsound
	8,		// speed
	20*FRACUNIT,		// radius
	56*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_posact,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_SSWV_RAISE1		// raisestate
    ),

    new mobjinfo_t(		// MT_KEEN
	72,		// doomednum
	statenum_t.S_KEENSTND,		// spawnstate
	100,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_KEENPAIN,		// painstate
	256,		// painchance
	sfxenum_t.sfx_keenpn,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_COMMKEEN,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_keendt,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	72*FRACUNIT,		// height
	10000000,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY|MF_SHOOTABLE|MF_COUNTKILL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_BOSSBRAIN
	88,		// doomednum
	statenum_t.S_BRAIN,		// spawnstate
	250,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_BRAIN_PAIN,		// painstate
	255,		// painchance
	sfxenum_t.sfx_bospn,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_BRAIN_DIE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_bosdth,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	10000000,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SHOOTABLE,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_BOSSSPIT
	89,		// doomednum
	statenum_t.S_BRAINEYE,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_BRAINEYESEE,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	32*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOSECTOR,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_BOSSTARGET
	87,		// doomednum
	statenum_t.S_NULL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	32*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOSECTOR,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_SPAWNSHOT
	-1,		// doomednum
	statenum_t.S_SPAWN1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_bospit,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_firxpl,		// deathsound
	10*FRACUNIT,		// speed
	6*FRACUNIT,		// radius
	32*FRACUNIT,		// height
	100,		// mass
	3,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY|MF_NOCLIP,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_SPAWNFIRE
	-1,		// doomednum
	statenum_t.S_SPAWNFIRE1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_BARREL
	2035,		// doomednum
	statenum_t.S_BAR1,		// spawnstate
	20,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_BEXP,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_barexp,		// deathsound
	0,		// speed
	10*FRACUNIT,		// radius
	42*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_TROOPSHOT
	-1,		// doomednum
	statenum_t.S_TBALL1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_firsht,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_TBALLX1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_firxpl,		// deathsound
	10*FRACUNIT,		// speed
	6*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	3,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_HEADSHOT
	-1,		// doomednum
	statenum_t.S_RBALL1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_firsht,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_RBALLX1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_firxpl,		// deathsound
	10*FRACUNIT,		// speed
	6*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	5,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_ROCKET
	-1,		// doomednum
	statenum_t.S_ROCKET,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_rlaunc,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_EXPLODE1,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_barexp,		// deathsound
	20*FRACUNIT,		// speed
	11*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	20,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_PLASMA
	-1,		// doomednum
	statenum_t.S_PLASBALL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_plasma,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_PLASEXP,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_firxpl,		// deathsound
	25*FRACUNIT,		// speed
	13*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	5,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_BFG
	-1,		// doomednum
	statenum_t.S_BFGSHOT,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_BFGLAND,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_rxplod,		// deathsound
	25*FRACUNIT,		// speed
	13*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	100,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_ARACHPLAZ
	-1,		// doomednum
	statenum_t.S_ARACH_PLAZ,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_plasma,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_ARACH_PLEX,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_firxpl,		// deathsound
	25*FRACUNIT,		// speed
	13*FRACUNIT,		// radius
	8*FRACUNIT,		// height
	100,		// mass
	5,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_PUFF
	-1,		// doomednum
	statenum_t.S_PUFF1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_BLOOD
	-1,		// doomednum
	statenum_t.S_BLOOD1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_TFOG
	-1,		// doomednum
	statenum_t.S_TFOG,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_IFOG
	-1,		// doomednum
	statenum_t.S_IFOG,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_TELEPORTMAN
	14,		// doomednum
	statenum_t.S_NULL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOSECTOR,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_EXTRABFG
	-1,		// doomednum
	statenum_t.S_BFGEXP,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC0
	2018,		// doomednum
	statenum_t.S_ARM1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC1
	2019,		// doomednum
	statenum_t.S_ARM2,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC2
	2014,		// doomednum
	statenum_t.S_BON1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC3
	2015,		// doomednum
	statenum_t.S_BON2,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC4
	5,		// doomednum
	statenum_t.S_BKEY,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_NOTDMATCH,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC5
	13,		// doomednum
	statenum_t.S_RKEY,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_NOTDMATCH,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC6
	6,		// doomednum
	statenum_t.S_YKEY,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_NOTDMATCH,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC7
	39,		// doomednum
	statenum_t.S_YSKULL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_NOTDMATCH,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC8
	38,		// doomednum
	statenum_t.S_RSKULL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_NOTDMATCH,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC9
	40,		// doomednum
	statenum_t.S_BSKULL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_NOTDMATCH,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC10
	2011,		// doomednum
	statenum_t.S_STIM,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC11
	2012,		// doomednum
	statenum_t.S_MEDI,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC12
	2013,		// doomednum
	statenum_t.S_SOUL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_INV
	2022,		// doomednum
	statenum_t.S_PINV,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC13
	2023,		// doomednum
	statenum_t.S_PSTR,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_INS
	2024,		// doomednum
	statenum_t.S_PINS,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC14
	2025,		// doomednum
	statenum_t.S_SUIT,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC15
	2026,		// doomednum
	statenum_t.S_PMAP,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC16
	2045,		// doomednum
	statenum_t.S_PVIS,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MEGA
	83,		// doomednum
	statenum_t.S_MEGA,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL|MF_COUNTITEM,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_CLIP
	2007,		// doomednum
	statenum_t.S_CLIP,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC17
	2048,		// doomednum
	statenum_t.S_AMMO,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC18
	2010,		// doomednum
	statenum_t.S_ROCK,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC19
	2046,		// doomednum
	statenum_t.S_BROK,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC20
	2047,		// doomednum
	statenum_t.S_CELL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC21
	17,		// doomednum
	statenum_t.S_CELP,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC22
	2008,		// doomednum
	statenum_t.S_SHEL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC23
	2049,		// doomednum
	statenum_t.S_SBOX,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC24
	8,		// doomednum
	statenum_t.S_BPAK,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC25
	2006,		// doomednum
	statenum_t.S_BFUG,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_CHAINGUN
	2002,		// doomednum
	statenum_t.S_MGUN,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC26
	2005,		// doomednum
	statenum_t.S_CSAW,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC27
	2003,		// doomednum
	statenum_t.S_LAUN,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC28
	2004,		// doomednum
	statenum_t.S_PLAS,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_SHOTGUN
	2001,		// doomednum
	statenum_t.S_SHOT,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_SUPERSHOTGUN
	82,		// doomednum
	statenum_t.S_SHOT2,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPECIAL,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC29
	85,		// doomednum
	statenum_t.S_TECHLAMP,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC30
	86,		// doomednum
	statenum_t.S_TECH2LAMP,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC31
	2028,		// doomednum
	statenum_t.S_COLU,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC32
	30,		// doomednum
	statenum_t.S_TALLGRNCOL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC33
	31,		// doomednum
	statenum_t.S_SHRTGRNCOL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC34
	32,		// doomednum
	statenum_t.S_TALLREDCOL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC35
	33,		// doomednum
	statenum_t.S_SHRTREDCOL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC36
	37,		// doomednum
	statenum_t.S_SKULLCOL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC37
	36,		// doomednum
	statenum_t.S_HEARTCOL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC38
	41,		// doomednum
	statenum_t.S_EVILEYE,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC39
	42,		// doomednum
	statenum_t.S_FLOATSKULL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC40
	43,		// doomednum
	statenum_t.S_TORCHTREE,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC41
	44,		// doomednum
	statenum_t.S_BLUETORCH,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC42
	45,		// doomednum
	statenum_t.S_GREENTORCH,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC43
	46,		// doomednum
	statenum_t.S_REDTORCH,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC44
	55,		// doomednum
	statenum_t.S_BTORCHSHRT,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC45
	56,		// doomednum
	statenum_t.S_GTORCHSHRT,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC46
	57,		// doomednum
	statenum_t.S_RTORCHSHRT,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC47
	47,		// doomednum
	statenum_t.S_STALAGTITE,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC48
	48,		// doomednum
	statenum_t.S_TECHPILLAR,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC49
	34,		// doomednum
	statenum_t.S_CANDLESTIK,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC50
	35,		// doomednum
	statenum_t.S_CANDELABRA,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC51
	49,		// doomednum
	statenum_t.S_BLOODYTWITCH,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	68*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC52
	50,		// doomednum
	statenum_t.S_MEAT2,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	84*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC53
	51,		// doomednum
	statenum_t.S_MEAT3,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	84*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC54
	52,		// doomednum
	statenum_t.S_MEAT4,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	68*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC55
	53,		// doomednum
	statenum_t.S_MEAT5,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	52*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC56
	59,		// doomednum
	statenum_t.S_MEAT2,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	84*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC57
	60,		// doomednum
	statenum_t.S_MEAT4,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	68*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC58
	61,		// doomednum
	statenum_t.S_MEAT3,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	52*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC59
	62,		// doomednum
	statenum_t.S_MEAT5,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	52*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC60
	63,		// doomednum
	statenum_t.S_BLOODYTWITCH,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	68*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC61
	22,		// doomednum
	statenum_t.S_HEAD_DIE6,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC62
	15,		// doomednum
	statenum_t.S_PLAY_DIE7,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC63
	18,		// doomednum
	statenum_t.S_POSS_DIE5,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC64
	21,		// doomednum
	statenum_t.S_SARG_DIE6,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC65
	23,		// doomednum
	statenum_t.S_SKULL_DIE6,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC66
	20,		// doomednum
	statenum_t.S_TROO_DIE5,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC67
	19,		// doomednum
	statenum_t.S_SPOS_DIE5,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC68
	10,		// doomednum
	statenum_t.S_PLAY_XDIE9,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC69
	12,		// doomednum
	statenum_t.S_PLAY_XDIE9,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC70
	28,		// doomednum
	statenum_t.S_HEADSONSTICK,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC71
	24,		// doomednum
	statenum_t.S_GIBS,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	0,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC72
	27,		// doomednum
	statenum_t.S_HEADONASTICK,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC73
	29,		// doomednum
	statenum_t.S_HEADCANDLES,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC74
	25,		// doomednum
	statenum_t.S_DEADSTICK,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC75
	26,		// doomednum
	statenum_t.S_LIVESTICK,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC76
	54,		// doomednum
	statenum_t.S_BIGTREE,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	32*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC77
	70,		// doomednum
	statenum_t.S_BBAR1,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC78
	73,		// doomednum
	statenum_t.S_HANGNOGUTS,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	88*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC79
	74,		// doomednum
	statenum_t.S_HANGBNOBRAIN,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	88*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC80
	75,		// doomednum
	statenum_t.S_HANGTLOOKDN,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	64*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC81
	76,		// doomednum
	statenum_t.S_HANGTSKULL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	64*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC82
	77,		// doomednum
	statenum_t.S_HANGTLOOKUP,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	64*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC83
	78,		// doomednum
	statenum_t.S_HANGTNOBRAIN,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	16*FRACUNIT,		// radius
	64*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_SOLID|MF_SPAWNCEILING|MF_NOGRAVITY,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC84
	79,		// doomednum
	statenum_t.S_COLONGIBS,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC85
	80,		// doomednum
	statenum_t.S_SMALLPOOL,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP,		// flags
	statenum_t.S_NULL		// raisestate
    ),

    new mobjinfo_t(		// MT_MISC86
	81,		// doomednum
	statenum_t.S_BRAINSTEM,		// spawnstate
	1000,		// spawnhealth
	statenum_t.S_NULL,		// seestate
	sfxenum_t.sfx_None,		// seesound
	8,		// reactiontime
	sfxenum_t.sfx_None,		// attacksound
	statenum_t.S_NULL,		// painstate
	0,		// painchance
	sfxenum_t.sfx_None,		// painsound
	statenum_t.S_NULL,		// meleestate
	statenum_t.S_NULL,		// missilestate
	statenum_t.S_NULL,		// deathstate
	statenum_t.S_NULL,		// xdeathstate
	sfxenum_t.sfx_None,		// deathsound
	0,		// speed
	20*FRACUNIT,		// radius
	16*FRACUNIT,		// height
	100,		// mass
	0,		// damage
	sfxenum_t.sfx_None,		// activesound
	MF_NOBLOCKMAP,		// flags
	statenum_t.S_NULL		// raisestate
    )
};

static {
// Need to set them to simulate pointer-like operations.
	for (int i=0;i<states.length;i++){
		states[i].id=i;
		
		//states[0]=null;
}
}
}


package data;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import w.CacheableDoomObject;
import w.DoomBuffer;

/** BSP Node structure on-disk */
public class mapnode_t
        implements CacheableDoomObject {

    public mapnode_t() {
        this.bbox = new short[2][4];
        this.children = new char[2];
    }

    /** Partition line from (x,y) to x+dx,y+dy) */
    public short x, y, dx, dy;

    /** Bounding box for each child, clip against view frustum. */
    public short[][] bbox;

    /** If NF_SUBSECTOR its a subsector, else it's a node of another subtree. 
     *  In simpler words: if the first bit is set, strip it and use the rest
     *  as a subtree index. Else it's a node index.
     * */
    public char[] children = new char[2]; // MAES: used to be unsigned short.

    public static int sizeOf() {
        return (8 + 16 + 4);
    }

    @Override
    public void unpack(ByteBuffer buf)
            throws IOException {
        buf.order(ByteOrder.LITTLE_ENDIAN);
        this.x = buf.getShort();
        this.y = buf.getShort();
        this.dx = buf.getShort();
        this.dy = buf.getShort();
        DoomBuffer.readShortArray(buf, this.bbox[0], 4);
        DoomBuffer.readShortArray(buf, this.bbox[1], 4);
        DoomBuffer.readCharArray(buf, this.children, 2);
    }

}

package data;

import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import w.CacheableDoomObject;
import w.DoomBuffer;
import w.IPackableDoomObject;
import w.IWritableDoomObject;

/**
 * A LineDef, as used for editing, and as input to the BSP builder.
 */
public class maplinedef_t implements CacheableDoomObject,IPackableDoomObject,IWritableDoomObject{

    public maplinedef_t() {
        this.sidenum = new char[2];
    }

    public char v1;

    public char v2;

    public short flags;

    public short special;

    public short tag;

    /** sidenum[1] will be 0xFFFF if one sided */
    public char[] sidenum;

    public static int sizeOf() {
        return 14;
    }

    @Override
    public void unpack(ByteBuffer buf)
            throws IOException {
    buf.order(ByteOrder.LITTLE_ENDIAN);
    this.v1 = buf.getChar();
    this.v2 = buf.getChar();
    this.flags = buf.getShort();
    this.special = buf.getShort();
    this.tag = buf.getShort();
    DoomBuffer.readCharArray(buf, this.sidenum, 2);
    }

	@Override
	public void write(DataOutputStream dos) throws IOException {
        // More efficient, avoids duplicating code and
        // handles little endian better.
        iobuffer.position(0);
        iobuffer.order(ByteOrder.LITTLE_ENDIAN);
        this.pack(iobuffer);
        dos.write(iobuffer.array());		
	}

	@Override
	public void pack(ByteBuffer buf) throws IOException {
	    buf.order(ByteOrder.LITTLE_ENDIAN);
	    buf.putChar(v1);
	    buf.putChar(v2);
	    buf.putShort(flags);
	    buf.putShort(special);
	    buf.putShort(tag);
	    buf.putChar(sidenum[0]);
	    buf.putChar(sidenum[1]);		
	}
	
	private static ByteBuffer iobuffer=ByteBuffer.allocate(maplinedef_t.sizeOf());
}

package data;

import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import w.CacheableDoomObject;
import w.IPackableDoomObject;
import w.IWritableDoomObject;

/**
 * This is the structure of a map vertex ON DISK: in memory it gets shifted and
 * expanded to fixed_t. Also, on disk it only exists as part of the VERTEXES
 * lump: it is not individually cacheable, even though it implements
 * CacheableDoomObject.
 */

public class mapvertex_t implements CacheableDoomObject,IWritableDoomObject,IPackableDoomObject {

    public mapvertex_t(short x, short y) {
        this.x = x;
        this.y = y;
    }

    public mapvertex_t() {
        this((short) 0, (short) 0);
    }

    public short x;

    public short y;

    public static int sizeOf() {
        return 4;
    }

    @Override
    public void unpack(ByteBuffer buf)
            throws IOException {
        buf.order(ByteOrder.LITTLE_ENDIAN);
        x = buf.getShort();
        y = buf.getShort();
    }

	@Override
	public void pack(ByteBuffer buf) throws IOException {
        buf.order(ByteOrder.LITTLE_ENDIAN);
        buf.putShort(x);
        buf.putShort(y);		
	}

	@Override
	public void write(DataOutputStream dos) throws IOException {
        // More efficient, avoids duplicating code and
        // handles little endian better.
        iobuffer.position(0);
        iobuffer.order(ByteOrder.LITTLE_ENDIAN);
        this.pack(iobuffer);
        dos.write(iobuffer.array());		
	}
	
	private static final ByteBuffer iobuffer=ByteBuffer.allocate(mapvertex_t.sizeOf());

}

package data;

import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import rr.sector_t;
import w.CacheableDoomObject;
import w.DoomBuffer;
import w.IPackableDoomObject;
import w.IWritableDoomObject;

/** Sector definition, from editing. */ 
public class mapsector_t implements CacheableDoomObject,IWritableDoomObject, IPackableDoomObject {
    
        public mapsector_t(){

        }
    
      public short     floorheight;
      public  short     ceilingheight;
      public  String floorpic;
      public  String        ceilingpic;
      public  short     lightlevel;
      public  short     special;
      public  short     tag;
      
    @Override
    public void unpack(ByteBuffer buf)
            throws IOException {
        buf.order(ByteOrder.LITTLE_ENDIAN);
        this.floorheight = buf.getShort();
        this.ceilingheight = buf.getShort();
        this.floorpic=DoomBuffer.getNullTerminatedString(buf,8).toUpperCase();
        this.ceilingpic=DoomBuffer.getNullTerminatedString(buf,8).toUpperCase();
        this.lightlevel= buf.getShort();
        this.special= buf.getShort();
        this.tag= buf.getShort();
    }
    
    public static int sizeOf() {
        return 26;
    }
    
    @Override
    public void write(DataOutputStream dos)
            throws IOException {    	
    	
        // More efficient, avoids duplicating code and
        // handles little endian better.
        iobuffer.position(0);
        iobuffer.order(ByteOrder.LITTLE_ENDIAN);
        this.pack(iobuffer);
        dos.write(iobuffer.array());
        
    }

    public void pack(ByteBuffer b) throws IOException {
        b.order(ByteOrder.LITTLE_ENDIAN);
        b.putShort(this.floorheight);
        b.putShort(this.ceilingheight);
        DoomBuffer.putNullTerminatedString(b, this.floorpic,8);
        DoomBuffer.putNullTerminatedString(b, this.ceilingpic,8);
        b.putShort(this.lightlevel);
        b.putShort(this.special);
        b.putShort(this.tag);
    }
    
    private static final ByteBuffer iobuffer=ByteBuffer.allocate(mapsector_t.sizeOf());
      
}

package data;

public class musicinfo_t {

    public musicinfo_t() {
    }

    
    public musicinfo_t(String name) {
        this.name = name;
    }
    
    public musicinfo_t(String name, int lumpnum) {
        this.name = name;
        this.lumpnum = lumpnum;
    }

    // up to 6-character name
    public String   name;

    // lump number of music
    public int     lumpnum;
    
    // music data
    public byte[] data;

    // music handle once registered
    public int handle;
}

package data;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import w.CacheableDoomObject;

/** SubSector, as generated by BSP. */

public class mapsubsector_t implements CacheableDoomObject{
    
        public mapsubsector_t(){
            
        }
        
      public char     numsegs;
      /** Index of first one, segs are stored sequentially. */
      public char     firstseg;
    @Override
    public void unpack(ByteBuffer buf)
            throws IOException {
        buf.order(ByteOrder.LITTLE_ENDIAN);
        this.numsegs = buf.getChar();
        this.firstseg = buf.getChar();
        
    } 
    
    public static int sizeOf(){
        return 4;
    }
}

package data;

/** This is actually used as a data type */

public enum spritenum_t {
	    SPR_TROO,
	    SPR_SHTG,
	    SPR_PUNG,
	    SPR_PISG,
	    SPR_PISF,
	    SPR_SHTF,
	    SPR_SHT2,
	    SPR_CHGG,
	    SPR_CHGF,
	    SPR_MISG,
	    SPR_MISF,
	    SPR_SAWG,
	    SPR_PLSG,
	    SPR_PLSF,
	    SPR_BFGG,
	    SPR_BFGF,
	    SPR_BLUD,
	    SPR_PUFF,
	    SPR_BAL1,
	    SPR_BAL2,
	    SPR_PLSS,
	    SPR_PLSE,
	    SPR_MISL,
	    SPR_BFS1,
	    SPR_BFE1,
	    SPR_BFE2,
	    SPR_TFOG,
	    SPR_IFOG,
	    SPR_PLAY,
	    SPR_POSS,
	    SPR_SPOS,
	    SPR_VILE,
	    SPR_FIRE,
	    SPR_FATB,
	    SPR_FBXP,
	    SPR_SKEL,
	    SPR_MANF,
	    SPR_FATT,
	    SPR_CPOS,
	    SPR_SARG,
	    SPR_HEAD,
	    SPR_BAL7,
	    SPR_BOSS,
	    SPR_BOS2,
	    SPR_SKUL,
	    SPR_SPID,
	    SPR_BSPI,
	    SPR_APLS,
	    SPR_APBX,
	    SPR_CYBR,
	    SPR_PAIN,
	    SPR_SSWV,
	    SPR_KEEN,
	    SPR_BBRN,
	    SPR_BOSF,
	    SPR_ARM1,
	    SPR_ARM2,
	    SPR_BAR1,
	    SPR_BEXP,
	    SPR_FCAN,
	    SPR_BON1,
	    SPR_BON2,
	    SPR_BKEY,
	    SPR_RKEY,
	    SPR_YKEY,
	    SPR_BSKU,
	    SPR_RSKU,
	    SPR_YSKU,
	    SPR_STIM,
	    SPR_MEDI,
	    SPR_SOUL,
	    SPR_PINV,
	    SPR_PSTR,
	    SPR_PINS,
	    SPR_MEGA,
	    SPR_SUIT,
	    SPR_PMAP,
	    SPR_PVIS,
	    SPR_CLIP,
	    SPR_AMMO,
	    SPR_ROCK,
	    SPR_BROK,
	    SPR_CELL,
	    SPR_CELP,
	    SPR_SHEL,
	    SPR_SBOX,
	    SPR_BPAK,
	    SPR_BFUG,
	    SPR_MGUN,
	    SPR_CSAW,
	    SPR_LAUN,
	    SPR_PLAS,
	    SPR_SHOT,
	    SPR_SGN2,
	    SPR_COLU,
	    SPR_SMT2,
	    SPR_GOR1,
	    SPR_POL2,
	    SPR_POL5,
	    SPR_POL4,
	    SPR_POL3,
	    SPR_POL1,
	    SPR_POL6,
	    SPR_GOR2,
	    SPR_GOR3,
	    SPR_GOR4,
	    SPR_GOR5,
	    SPR_SMIT,
	    SPR_COL1,
	    SPR_COL2,
	    SPR_COL3,
	    SPR_COL4,
	    SPR_CAND,
	    SPR_CBRA,
	    SPR_COL6,
	    SPR_TRE1,
	    SPR_TRE2,
	    SPR_ELEC,
	    SPR_CEYE,
	    SPR_FSKU,
	    SPR_COL5,
	    SPR_TBLU,
	    SPR_TGRN,
	    SPR_TRED,
	    SPR_SMBT,
	    SPR_SMGT,
	    SPR_SMRT,
	    SPR_HDB1,
	    SPR_HDB2,
	    SPR_HDB3,
	    SPR_HDB4,
	    SPR_HDB5,
	    SPR_HDB6,
	    SPR_POB1,
	    SPR_POB2,
	    SPR_BRS1,
	    SPR_TLMP,
	    SPR_TLP2,
	    NUMSPRITES
	};


package data;

import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import w.CacheableDoomObject;
import w.IPackableDoomObject;
import w.IWritableDoomObject;

/** mapthing_t ... same on disk AND in memory, wow?! */

public class mapthing_t implements CacheableDoomObject,IPackableDoomObject,IWritableDoomObject,Cloneable{
    public short x;

    public short y;

    public short angle;

    public short type;

    public short options;

    public mapthing_t() {
    }

    public mapthing_t(mapthing_t source) {
        this.copyFrom(source);
    }

    public static int sizeOf() {
        return 10;
    }

    @Override
    public void unpack(ByteBuffer buf)
            throws IOException {
        buf.order(ByteOrder.LITTLE_ENDIAN);
        this.x = buf.getShort();
        this.y = buf.getShort();
        this.angle = buf.getShort();
        this.type = buf.getShort();
        this.options = buf.getShort();
        
    }
    
    public void copyFrom(mapthing_t source){

        this.x=source.x;
        this.y=source.y;
        this.angle=source.angle;
        this.options=source.options;
        this.type=source.type;
    }

    @Override
    public void write(DataOutputStream f)
            throws IOException {
        
        // More efficient, avoids duplicating code and
        // handles little endian better.
        iobuffer.position(0);
        iobuffer.order(ByteOrder.LITTLE_ENDIAN);
        this.pack(iobuffer);
        f.write(iobuffer.array());
        
    }

    public void pack(ByteBuffer b) {
        b.order(ByteOrder.LITTLE_ENDIAN);
        b.putShort(x);
        b.putShort(y);
        b.putShort(angle);
        b.putShort(type);
        b.putShort(options);
    }
    
    private static ByteBuffer iobuffer=ByteBuffer.allocate(mapthing_t.sizeOf());
}
package data;

import static m.fixed_t.FRACUNIT;
import static m.fixed_t.MAPFRACUNIT;

/** Everything that constitutes a removable limit should go here */

public final class Limits {

	// Obvious rendering limits
	public static final int MAXVISPLANES = 128;
	public static final int MAXSEGS = 32;
	public static final int MAXVISSPRITES = 128;
	public static final int MAXDRAWSEGS = 256;
	// MAES: Moved MAXOPENINGS to renderer state, it's scale dependant.
	public static final int CEILSPEED = MAPFRACUNIT;
	public static final int CEILWAIT = 150;
	public static final int MAXCEILINGS = 30;

	public static final int MAXANIMS = 32;

	/** Animating line specials */
	public static final int MAXLINEANIMS = 64;

	// These are only used in the renderer, effectively putting
	// a limit to the size of lookup tables for screen buffers.
	public static final int MAXWIDTH = 1600;
	public static final int MAXHEIGHT = 1200;

	// Command line/file limits
	public static final int MAXWADFILES = 20;
	public static final int MAXARGVS = 100;

	// The maximum number of players, multiplayer/networking.
	// Max computers/players in a game. AFFECTS SAVEGAMES.
	public static final int MAXPLAYERS = 4;
	public final static int MAXNETNODES = 8;

	/** Some quirky engine limits */
	public static final int MAXEVENTS = 64;
	
	/** max # of wall switch TYPES in a level */
	public static final int MAXSWITCHES = 50;

	/** 20 adjoining sectors max! */
	public static final int MAX_ADJOINING_SECTORS = 20;

	// 4 players, 4 buttons each at once, max.
	public static final int MAXBUTTONS = 16;

	// 1 second, in ticks.
	public static final int BUTTONTIME = 35;

	/**
	 * keep track of special lines as they are hit, but don't process them until
	 * the move is proven valid
	 */
	public static final int MAXSPECIALCROSS = 8;
	public static final int MAXHEALTH = 100;

	/**
	 * MAXRADIUS is for precalculated sector block boxes the spider demon is
	 * larger, but we do not have any moving sectors nearby
	 */
	public static final int MAXRADIUS = 32 * FRACUNIT;

	public static final int MAXINTERCEPTS = 128;
	public static final int MAXMOVE = (30 * MAPFRACUNIT);

	/** Player spawn spots for deathmatch. */
	public static final int MAX_DM_STARTS = 10;

	// C's "chars" are actually Java signed bytes.
	public static final byte MAXCHAR = ((byte) 0x7f);
	public static final byte MINCHAR = ((byte) 0x80);

	// 16-bit integers...
	public static final short MAXSHORT = ((short) 0x7fff);
	public static final short MINSHORT = ((short) 0x8000);

	// Max pos 32-bit int.
	public static final int MAXINT = ((int) 0x7fffffff);
	public static final long MAXLONG = ((long) 0x7fffffff);

	// Max negative 32-bit integer. These are considered to be the same.
	public static final int MININT = ((int) 0x80000000);
	public static final long MINLONG = ((long) 0x80000000);

	// Buffering/memory limits.
	public static final int SAVEGAMESIZE = 0x2c000;

	public static final int SAVESTRINGSIZE = 24;
	public static final int VERSIONSIZE = 16;

	public static final int PLATWAIT = 3;
	public static final int PLATSPEED = MAPFRACUNIT;
	public static final int MAXPLATS = 30;
	public static final int MAXSKULLS = 20;
	public static final int NUMBRAINTARGETS=32;
	public static final int NUMMOBJTYPES=mobjtype_t.NUMMOBJTYPES.ordinal();
	
}

package data;

import static data.Tables.FINEANGLES;

/** Sine and Cosine.
 *  Java can't have that mush initialization data in one file, so I had to separate it.
 * 
 * @author Maes
 *
 */

public class SineCosine {

 // MAES: original size was 10240, but includes 5PI/4 periods.
 // We can get away with ints on this one because of the small range.
 // MAES: WTF? -64 ~ 64K range... so 17-bit accuracy? heh.

    /**
     * Original size was 10240, but includes 5PI/4 periods.
     * We can get away with ints on this one because of the small range.
     * MAES: WTF? -64 ~ 64K range... so 17-bit accuracy? heh.
     */
    
    public static int[] finesine=
    {
        25,75,125,175,226,276,326,376,
        427,477,527,578,628,678,728,779,
        829,879,929,980,1030,1080,1130,1181,
        1231,1281,1331,1382,1432,1482,1532,1583,
        1633,1683,1733,1784,1834,1884,1934,1985,
        2035,2085,2135,2186,2236,2286,2336,2387,
        2437,2487,2537,2587,2638,2688,2738,2788,
        2839,2889,2939,2989,3039,3090,3140,3190,
        3240,3291,3341,3391,3441,3491,3541,3592,
        3642,3692,3742,3792,3843,3893,3943,3993,
        4043,4093,4144,4194,4244,4294,4344,4394,
        4445,4495,4545,4595,4645,4695,4745,4796,
        4846,4896,4946,4996,5046,5096,5146,5197,
        5247,5297,5347,5397,5447,5497,5547,5597,
        5647,5697,5748,5798,5848,5898,5948,5998,
        6048,6098,6148,6198,6248,6298,6348,6398,
        6448,6498,6548,6598,6648,6698,6748,6798,
        6848,6898,6948,6998,7048,7098,7148,7198,
        7248,7298,7348,7398,7448,7498,7548,7598,
        7648,7697,7747,7797,7847,7897,7947,7997,
        8047,8097,8147,8196,8246,8296,8346,8396,
        8446,8496,8545,8595,8645,8695,8745,8794,
        8844,8894,8944,8994,9043,9093,9143,9193,
        9243,9292,9342,9392,9442,9491,9541,9591,
        9640,9690,9740,9790,9839,9889,9939,9988,
        10038,10088,10137,10187,10237,10286,10336,10386,
        10435,10485,10534,10584,10634,10683,10733,10782,
        10832,10882,10931,10981,11030,11080,11129,11179,
        11228,11278,11327,11377,11426,11476,11525,11575,
        11624,11674,11723,11773,11822,11872,11921,11970,
        12020,12069,12119,12168,12218,12267,12316,12366,
        12415,12464,12514,12563,12612,12662,12711,12760,
        12810,12859,12908,12957,13007,13056,13105,13154,
        13204,13253,13302,13351,13401,13450,13499,13548,
        13597,13647,13696,13745,13794,13843,13892,13941,
        13990,14040,14089,14138,14187,14236,14285,14334,
        14383,14432,14481,14530,14579,14628,14677,14726,
        14775,14824,14873,14922,14971,15020,15069,15118,
        15167,15215,15264,15313,15362,15411,15460,15509,
        15557,15606,15655,15704,15753,15802,15850,15899,
        15948,15997,16045,16094,16143,16191,16240,16289,
        16338,16386,16435,16484,16532,16581,16629,16678,
        16727,16775,16824,16872,16921,16970,17018,17067,
        17115,17164,17212,17261,17309,17358,17406,17455,
        17503,17551,17600,17648,17697,17745,17793,17842,
        17890,17939,17987,18035,18084,18132,18180,18228,
        18277,18325,18373,18421,18470,18518,18566,18614,
        18663,18711,18759,18807,18855,18903,18951,19000,
        19048,19096,19144,19192,19240,19288,19336,19384,
        19432,19480,19528,19576,19624,19672,19720,19768,
        19816,19864,19912,19959,20007,20055,20103,20151,
        20199,20246,20294,20342,20390,20438,20485,20533,
        20581,20629,20676,20724,20772,20819,20867,20915,
        20962,21010,21057,21105,21153,21200,21248,21295,
        21343,21390,21438,21485,21533,21580,21628,21675,
        21723,21770,21817,21865,21912,21960,22007,22054,
        22102,22149,22196,22243,22291,22338,22385,22433,
        22480,22527,22574,22621,22668,22716,22763,22810,
        22857,22904,22951,22998,23045,23092,23139,23186,
        23233,23280,23327,23374,23421,23468,23515,23562,
        23609,23656,23703,23750,23796,23843,23890,23937,
        23984,24030,24077,24124,24171,24217,24264,24311,
        24357,24404,24451,24497,24544,24591,24637,24684,
        24730,24777,24823,24870,24916,24963,25009,25056,
        25102,25149,25195,25241,25288,25334,25381,25427,
        25473,25520,25566,25612,25658,25705,25751,25797,
        25843,25889,25936,25982,26028,26074,26120,26166,
        26212,26258,26304,26350,26396,26442,26488,26534,
        26580,26626,26672,26718,26764,26810,26856,26902,
        26947,26993,27039,27085,27131,27176,27222,27268,
        27313,27359,27405,27450,27496,27542,27587,27633,
        27678,27724,27770,27815,27861,27906,27952,27997,
        28042,28088,28133,28179,28224,28269,28315,28360,
        28405,28451,28496,28541,28586,28632,28677,28722,
        28767,28812,28858,28903,28948,28993,29038,29083,
        29128,29173,29218,29263,29308,29353,29398,29443,
        29488,29533,29577,29622,29667,29712,29757,29801,
        29846,29891,29936,29980,30025,30070,30114,30159,
        30204,30248,30293,30337,30382,30426,30471,30515,
        30560,30604,30649,30693,30738,30782,30826,30871,
        30915,30959,31004,31048,31092,31136,31181,31225,
        31269,31313,31357,31402,31446,31490,31534,31578,
        31622,31666,31710,31754,31798,31842,31886,31930,
        31974,32017,32061,32105,32149,32193,32236,32280,
        32324,32368,32411,32455,32499,32542,32586,32630,
        32673,32717,32760,32804,32847,32891,32934,32978,
        33021,33065,33108,33151,33195,33238,33281,33325,
        33368,33411,33454,33498,33541,33584,33627,33670,
        33713,33756,33799,33843,33886,33929,33972,34015,
        34057,34100,34143,34186,34229,34272,34315,34358,
        34400,34443,34486,34529,34571,34614,34657,34699,
        34742,34785,34827,34870,34912,34955,34997,35040,
        35082,35125,35167,35210,35252,35294,35337,35379,
        35421,35464,35506,35548,35590,35633,35675,35717,
        35759,35801,35843,35885,35927,35969,36011,36053,
        36095,36137,36179,36221,36263,36305,36347,36388,
        36430,36472,36514,36555,36597,36639,36681,36722,
        36764,36805,36847,36889,36930,36972,37013,37055,
        37096,37137,37179,37220,37262,37303,37344,37386,
        37427,37468,37509,37551,37592,37633,37674,37715,
        37756,37797,37838,37879,37920,37961,38002,38043,
        38084,38125,38166,38207,38248,38288,38329,38370,
        38411,38451,38492,38533,38573,38614,38655,38695,
        38736,38776,38817,38857,38898,38938,38979,39019,
        39059,39100,39140,39180,39221,39261,39301,39341,
        39382,39422,39462,39502,39542,39582,39622,39662,
        39702,39742,39782,39822,39862,39902,39942,39982,
        40021,40061,40101,40141,40180,40220,40260,40300,
        40339,40379,40418,40458,40497,40537,40576,40616,
        40655,40695,40734,40773,40813,40852,40891,40931,
        40970,41009,41048,41087,41127,41166,41205,41244,
        41283,41322,41361,41400,41439,41478,41517,41556,
        41595,41633,41672,41711,41750,41788,41827,41866,
        41904,41943,41982,42020,42059,42097,42136,42174,
        42213,42251,42290,42328,42366,42405,42443,42481,
        42520,42558,42596,42634,42672,42711,42749,42787,
        42825,42863,42901,42939,42977,43015,43053,43091,
        43128,43166,43204,43242,43280,43317,43355,43393,
        43430,43468,43506,43543,43581,43618,43656,43693,
        43731,43768,43806,43843,43880,43918,43955,43992,
        44029,44067,44104,44141,44178,44215,44252,44289,
        44326,44363,44400,44437,44474,44511,44548,44585,
        44622,44659,44695,44732,44769,44806,44842,44879,
        44915,44952,44989,45025,45062,45098,45135,45171,
        45207,45244,45280,45316,45353,45389,45425,45462,
        45498,45534,45570,45606,45642,45678,45714,45750,
        45786,45822,45858,45894,45930,45966,46002,46037,
        46073,46109,46145,46180,46216,46252,46287,46323,
        46358,46394,46429,46465,46500,46536,46571,46606,
        46642,46677,46712,46747,46783,46818,46853,46888,
        46923,46958,46993,47028,47063,47098,47133,47168,
        47203,47238,47273,47308,47342,47377,47412,47446,
        47481,47516,47550,47585,47619,47654,47688,47723,
        47757,47792,47826,47860,47895,47929,47963,47998,
        48032,48066,48100,48134,48168,48202,48237,48271,
        48305,48338,48372,48406,48440,48474,48508,48542,
        48575,48609,48643,48676,48710,48744,48777,48811,
        48844,48878,48911,48945,48978,49012,49045,49078,
        49112,49145,49178,49211,49244,49278,49311,49344,
        49377,49410,49443,49476,49509,49542,49575,49608,
        49640,49673,49706,49739,49771,49804,49837,49869,
        49902,49935,49967,50000,50032,50065,50097,50129,
        50162,50194,50226,50259,50291,50323,50355,50387,
        50420,50452,50484,50516,50548,50580,50612,50644,
        50675,50707,50739,50771,50803,50834,50866,50898,
        50929,50961,50993,51024,51056,51087,51119,51150,
        51182,51213,51244,51276,51307,51338,51369,51401,
        51432,51463,51494,51525,51556,51587,51618,51649,
        51680,51711,51742,51773,51803,51834,51865,51896,
        51926,51957,51988,52018,52049,52079,52110,52140,
        52171,52201,52231,52262,52292,52322,52353,52383,
        52413,52443,52473,52503,52534,52564,52594,52624,
        52653,52683,52713,52743,52773,52803,52832,52862,
        52892,52922,52951,52981,53010,53040,53069,53099,
        53128,53158,53187,53216,53246,53275,53304,53334,
        53363,53392,53421,53450,53479,53508,53537,53566,
        53595,53624,53653,53682,53711,53739,53768,53797,
        53826,53854,53883,53911,53940,53969,53997,54026,
        54054,54082,54111,54139,54167,54196,54224,54252,
        54280,54308,54337,54365,54393,54421,54449,54477,
        54505,54533,54560,54588,54616,54644,54672,54699,
        54727,54755,54782,54810,54837,54865,54892,54920,
        54947,54974,55002,55029,55056,55084,55111,55138,
        55165,55192,55219,55246,55274,55300,55327,55354,
        55381,55408,55435,55462,55489,55515,55542,55569,
        55595,55622,55648,55675,55701,55728,55754,55781,
        55807,55833,55860,55886,55912,55938,55965,55991,
        56017,56043,56069,56095,56121,56147,56173,56199,
        56225,56250,56276,56302,56328,56353,56379,56404,
        56430,56456,56481,56507,56532,56557,56583,56608,
        56633,56659,56684,56709,56734,56760,56785,56810,
        56835,56860,56885,56910,56935,56959,56984,57009,
        57034,57059,57083,57108,57133,57157,57182,57206,
        57231,57255,57280,57304,57329,57353,57377,57402,
        57426,57450,57474,57498,57522,57546,57570,57594,
        57618,57642,57666,57690,57714,57738,57762,57785,
        57809,57833,57856,57880,57903,57927,57950,57974,
        57997,58021,58044,58067,58091,58114,58137,58160,
        58183,58207,58230,58253,58276,58299,58322,58345,
        58367,58390,58413,58436,58459,58481,58504,58527,
        58549,58572,58594,58617,58639,58662,58684,58706,
        58729,58751,58773,58795,58818,58840,58862,58884,
        58906,58928,58950,58972,58994,59016,59038,59059,
        59081,59103,59125,59146,59168,59190,59211,59233,
        59254,59276,59297,59318,59340,59361,59382,59404,
        59425,59446,59467,59488,59509,59530,59551,59572,
        59593,59614,59635,59656,59677,59697,59718,59739,
        59759,59780,59801,59821,59842,59862,59883,59903,
        59923,59944,59964,59984,60004,60025,60045,60065,
        60085,60105,60125,60145,60165,60185,60205,60225,
        60244,60264,60284,60304,60323,60343,60363,60382,
        60402,60421,60441,60460,60479,60499,60518,60537,
        60556,60576,60595,60614,60633,60652,60671,60690,
        60709,60728,60747,60766,60785,60803,60822,60841,
        60859,60878,60897,60915,60934,60952,60971,60989,
        61007,61026,61044,61062,61081,61099,61117,61135,
        61153,61171,61189,61207,61225,61243,61261,61279,
        61297,61314,61332,61350,61367,61385,61403,61420,
        61438,61455,61473,61490,61507,61525,61542,61559,
        61577,61594,61611,61628,61645,61662,61679,61696,
        61713,61730,61747,61764,61780,61797,61814,61831,
        61847,61864,61880,61897,61913,61930,61946,61963,
        61979,61995,62012,62028,62044,62060,62076,62092,
        62108,62125,62141,62156,62172,62188,62204,62220,
        62236,62251,62267,62283,62298,62314,62329,62345,
        62360,62376,62391,62407,62422,62437,62453,62468,
        62483,62498,62513,62528,62543,62558,62573,62588,
        62603,62618,62633,62648,62662,62677,62692,62706,
        62721,62735,62750,62764,62779,62793,62808,62822,
        62836,62850,62865,62879,62893,62907,62921,62935,
        62949,62963,62977,62991,63005,63019,63032,63046,
        63060,63074,63087,63101,63114,63128,63141,63155,
        63168,63182,63195,63208,63221,63235,63248,63261,
        63274,63287,63300,63313,63326,63339,63352,63365,
        63378,63390,63403,63416,63429,63441,63454,63466,
        63479,63491,63504,63516,63528,63541,63553,63565,
        63578,63590,63602,63614,63626,63638,63650,63662,
        63674,63686,63698,63709,63721,63733,63745,63756,
        63768,63779,63791,63803,63814,63825,63837,63848,
        63859,63871,63882,63893,63904,63915,63927,63938,
        63949,63960,63971,63981,63992,64003,64014,64025,
        64035,64046,64057,64067,64078,64088,64099,64109,
        64120,64130,64140,64151,64161,64171,64181,64192,
        64202,64212,64222,64232,64242,64252,64261,64271,
        64281,64291,64301,64310,64320,64330,64339,64349,
        64358,64368,64377,64387,64396,64405,64414,64424,
        64433,64442,64451,64460,64469,64478,64487,64496,
        64505,64514,64523,64532,64540,64549,64558,64566,
        64575,64584,64592,64601,64609,64617,64626,64634,
        64642,64651,64659,64667,64675,64683,64691,64699,
        64707,64715,64723,64731,64739,64747,64754,64762,
        64770,64777,64785,64793,64800,64808,64815,64822,
        64830,64837,64844,64852,64859,64866,64873,64880,
        64887,64895,64902,64908,64915,64922,64929,64936,
        64943,64949,64956,64963,64969,64976,64982,64989,
        64995,65002,65008,65015,65021,65027,65033,65040,
        65046,65052,65058,65064,65070,65076,65082,65088,
        65094,65099,65105,65111,65117,65122,65128,65133,
        65139,65144,65150,65155,65161,65166,65171,65177,
        65182,65187,65192,65197,65202,65207,65212,65217,
        65222,65227,65232,65237,65242,65246,65251,65256,
        65260,65265,65270,65274,65279,65283,65287,65292,
        65296,65300,65305,65309,65313,65317,65321,65325,
        65329,65333,65337,65341,65345,65349,65352,65356,
        65360,65363,65367,65371,65374,65378,65381,65385,
        65388,65391,65395,65398,65401,65404,65408,65411,
        65414,65417,65420,65423,65426,65429,65431,65434,
        65437,65440,65442,65445,65448,65450,65453,65455,
        65458,65460,65463,65465,65467,65470,65472,65474,
        65476,65478,65480,65482,65484,65486,65488,65490,
        65492,65494,65496,65497,65499,65501,65502,65504,
        65505,65507,65508,65510,65511,65513,65514,65515,
        65516,65518,65519,65520,65521,65522,65523,65524,
        65525,65526,65527,65527,65528,65529,65530,65530,
        65531,65531,65532,65532,65533,65533,65534,65534,
        65534,65535,65535,65535,65535,65535,65535,65535,
        65535,65535,65535,65535,65535,65535,65535,65534,
        65534,65534,65533,65533,65532,65532,65531,65531,
        65530,65530,65529,65528,65527,65527,65526,65525,
        65524,65523,65522,65521,65520,65519,65518,65516,
        65515,65514,65513,65511,65510,65508,65507,65505,
        65504,65502,65501,65499,65497,65496,65494,65492,
        65490,65488,65486,65484,65482,65480,65478,65476,
        65474,65472,65470,65467,65465,65463,65460,65458,
        65455,65453,65450,65448,65445,65442,65440,65437,
        65434,65431,65429,65426,65423,65420,65417,65414,
        65411,65408,65404,65401,65398,65395,65391,65388,
        65385,65381,65378,65374,65371,65367,65363,65360,
        65356,65352,65349,65345,65341,65337,65333,65329,
        65325,65321,65317,65313,65309,65305,65300,65296,
        65292,65287,65283,65279,65274,65270,65265,65260,
        65256,65251,65246,65242,65237,65232,65227,65222,
        65217,65212,65207,65202,65197,65192,65187,65182,
        65177,65171,65166,65161,65155,65150,65144,65139,
        65133,65128,65122,65117,65111,65105,65099,65094,
        65088,65082,65076,65070,65064,65058,65052,65046,
        65040,65033,65027,65021,65015,65008,65002,64995,
        64989,64982,64976,64969,64963,64956,64949,64943,
        64936,64929,64922,64915,64908,64902,64895,64887,
        64880,64873,64866,64859,64852,64844,64837,64830,
        64822,64815,64808,64800,64793,64785,64777,64770,
        64762,64754,64747,64739,64731,64723,64715,64707,
        64699,64691,64683,64675,64667,64659,64651,64642,
        64634,64626,64617,64609,64600,64592,64584,64575,
        64566,64558,64549,64540,64532,64523,64514,64505,
        64496,64487,64478,64469,64460,64451,64442,64433,
        64424,64414,64405,64396,64387,64377,64368,64358,
        64349,64339,64330,64320,64310,64301,64291,64281,
        64271,64261,64252,64242,64232,64222,64212,64202,
        64192,64181,64171,64161,64151,64140,64130,64120,
        64109,64099,64088,64078,64067,64057,64046,64035,
        64025,64014,64003,63992,63981,63971,63960,63949,
        63938,63927,63915,63904,63893,63882,63871,63859,
        63848,63837,63825,63814,63803,63791,63779,63768,
        63756,63745,63733,63721,63709,63698,63686,63674,
        63662,63650,63638,63626,63614,63602,63590,63578,
        63565,63553,63541,63528,63516,63504,63491,63479,
        63466,63454,63441,63429,63416,63403,63390,63378,
        63365,63352,63339,63326,63313,63300,63287,63274,
        63261,63248,63235,63221,63208,63195,63182,63168,
        63155,63141,63128,63114,63101,63087,63074,63060,
        63046,63032,63019,63005,62991,62977,62963,62949,
        62935,62921,62907,62893,62879,62865,62850,62836,
        62822,62808,62793,62779,62764,62750,62735,62721,
        62706,62692,62677,62662,62648,62633,62618,62603,
        62588,62573,62558,62543,62528,62513,62498,62483,
        62468,62453,62437,62422,62407,62391,62376,62360,
        62345,62329,62314,62298,62283,62267,62251,62236,
        62220,62204,62188,62172,62156,62141,62125,62108,
        62092,62076,62060,62044,62028,62012,61995,61979,
        61963,61946,61930,61913,61897,61880,61864,61847,
        61831,61814,61797,61780,61764,61747,61730,61713,
        61696,61679,61662,61645,61628,61611,61594,61577,
        61559,61542,61525,61507,61490,61473,61455,61438,
        61420,61403,61385,61367,61350,61332,61314,61297,
        61279,61261,61243,61225,61207,61189,61171,61153,
        61135,61117,61099,61081,61062,61044,61026,61007,
        60989,60971,60952,60934,60915,60897,60878,60859,
        60841,60822,60803,60785,60766,60747,60728,60709,
        60690,60671,60652,60633,60614,60595,60576,60556,
        60537,60518,60499,60479,60460,60441,60421,60402,
        60382,60363,60343,60323,60304,60284,60264,60244,
        60225,60205,60185,60165,60145,60125,60105,60085,
        60065,60045,60025,60004,59984,59964,59944,59923,
        59903,59883,59862,59842,59821,59801,59780,59759,
        59739,59718,59697,59677,59656,59635,59614,59593,
        59572,59551,59530,59509,59488,59467,59446,59425,
        59404,59382,59361,59340,59318,59297,59276,59254,
        59233,59211,59190,59168,59146,59125,59103,59081,
        59059,59038,59016,58994,58972,58950,58928,58906,
        58884,58862,58840,58818,58795,58773,58751,58729,
        58706,58684,58662,58639,58617,58594,58572,58549,
        58527,58504,58481,58459,58436,58413,58390,58367,
        58345,58322,58299,58276,58253,58230,58207,58183,
        58160,58137,58114,58091,58067,58044,58021,57997,
        57974,57950,57927,57903,57880,57856,57833,57809,
        57785,57762,57738,57714,57690,57666,57642,57618,
        57594,57570,57546,57522,57498,57474,57450,57426,
        57402,57377,57353,57329,57304,57280,57255,57231,
        57206,57182,57157,57133,57108,57083,57059,57034,
        57009,56984,56959,56935,56910,56885,56860,56835,
        56810,56785,56760,56734,56709,56684,56659,56633,
        56608,56583,56557,56532,56507,56481,56456,56430,
        56404,56379,56353,56328,56302,56276,56250,56225,
        56199,56173,56147,56121,56095,56069,56043,56017,
        55991,55965,55938,55912,55886,55860,55833,55807,
        55781,55754,55728,55701,55675,55648,55622,55595,
        55569,55542,55515,55489,55462,55435,55408,55381,
        55354,55327,55300,55274,55246,55219,55192,55165,
        55138,55111,55084,55056,55029,55002,54974,54947,
        54920,54892,54865,54837,54810,54782,54755,54727,
        54699,54672,54644,54616,54588,54560,54533,54505,
        54477,54449,54421,54393,54365,54337,54308,54280,
        54252,54224,54196,54167,54139,54111,54082,54054,
        54026,53997,53969,53940,53911,53883,53854,53826,
        53797,53768,53739,53711,53682,53653,53624,53595,
        53566,53537,53508,53479,53450,53421,53392,53363,
        53334,53304,53275,53246,53216,53187,53158,53128,
        53099,53069,53040,53010,52981,52951,52922,52892,
        52862,52832,52803,52773,52743,52713,52683,52653,
        52624,52594,52564,52534,52503,52473,52443,52413,
        52383,52353,52322,52292,52262,52231,52201,52171,
        52140,52110,52079,52049,52018,51988,51957,51926,
        51896,51865,51834,51803,51773,51742,51711,51680,
        51649,51618,51587,51556,51525,51494,51463,51432,
        51401,51369,51338,51307,51276,51244,51213,51182,
        51150,51119,51087,51056,51024,50993,50961,50929,
        50898,50866,50834,50803,50771,50739,50707,50675,
        50644,50612,50580,50548,50516,50484,50452,50420,
        50387,50355,50323,50291,50259,50226,50194,50162,
        50129,50097,50065,50032,50000,49967,49935,49902,
        49869,49837,49804,49771,49739,49706,49673,49640,
        49608,49575,49542,49509,49476,49443,49410,49377,
        49344,49311,49278,49244,49211,49178,49145,49112,
        49078,49045,49012,48978,48945,48911,48878,48844,
        48811,48777,48744,48710,48676,48643,48609,48575,
        48542,48508,48474,48440,48406,48372,48338,48304,
        48271,48237,48202,48168,48134,48100,48066,48032,
        47998,47963,47929,47895,47860,47826,47792,47757,
        47723,47688,47654,47619,47585,47550,47516,47481,
        47446,47412,47377,47342,47308,47273,47238,47203,
        47168,47133,47098,47063,47028,46993,46958,46923,
        46888,46853,46818,46783,46747,46712,46677,46642,
        46606,46571,46536,46500,46465,46429,46394,46358,
        46323,46287,46252,46216,46180,46145,46109,46073,
        46037,46002,45966,45930,45894,45858,45822,45786,
        45750,45714,45678,45642,45606,45570,45534,45498,
        45462,45425,45389,45353,45316,45280,45244,45207,
        45171,45135,45098,45062,45025,44989,44952,44915,
        44879,44842,44806,44769,44732,44695,44659,44622,
        44585,44548,44511,44474,44437,44400,44363,44326,
        44289,44252,44215,44178,44141,44104,44067,44029,
        43992,43955,43918,43880,43843,43806,43768,43731,
        43693,43656,43618,43581,43543,43506,43468,43430,
        43393,43355,43317,43280,43242,43204,43166,43128,
        43091,43053,43015,42977,42939,42901,42863,42825,
        42787,42749,42711,42672,42634,42596,42558,42520,
        42481,42443,42405,42366,42328,42290,42251,42213,
        42174,42136,42097,42059,42020,41982,41943,41904,
        41866,41827,41788,41750,41711,41672,41633,41595,
        41556,41517,41478,41439,41400,41361,41322,41283,
        41244,41205,41166,41127,41088,41048,41009,40970,
        40931,40891,40852,40813,40773,40734,40695,40655,
        40616,40576,40537,40497,40458,40418,40379,40339,
        40300,40260,40220,40180,40141,40101,40061,40021,
        39982,39942,39902,39862,39822,39782,39742,39702,
        39662,39622,39582,39542,39502,39462,39422,39382,
        39341,39301,39261,39221,39180,39140,39100,39059,
        39019,38979,38938,38898,38857,38817,38776,38736,
        38695,38655,38614,38573,38533,38492,38451,38411,
        38370,38329,38288,38248,38207,38166,38125,38084,
        38043,38002,37961,37920,37879,37838,37797,37756,
        37715,37674,37633,37592,37551,37509,37468,37427,
        37386,37344,37303,37262,37220,37179,37137,37096,
        37055,37013,36972,36930,36889,36847,36805,36764,
        36722,36681,36639,36597,36556,36514,36472,36430,
        36388,36347,36305,36263,36221,36179,36137,36095,
        36053,36011,35969,35927,35885,35843,35801,35759,
        35717,35675,35633,35590,35548,35506,35464,35421,
        35379,35337,35294,35252,35210,35167,35125,35082,
        35040,34997,34955,34912,34870,34827,34785,34742,
        34699,34657,34614,34571,34529,34486,34443,34400,
        34358,34315,34272,34229,34186,34143,34100,34057,
        34015,33972,33929,33886,33843,33799,33756,33713,
        33670,33627,33584,33541,33498,33454,33411,33368,
        33325,33281,33238,33195,33151,33108,33065,33021,
        32978,32934,32891,32847,32804,32760,32717,32673,
        32630,32586,32542,32499,32455,32411,32368,32324,
        32280,32236,32193,32149,32105,32061,32017,31974,
        31930,31886,31842,31798,31754,31710,31666,31622,
        31578,31534,31490,31446,31402,31357,31313,31269,
        31225,31181,31136,31092,31048,31004,30959,30915,
        30871,30826,30782,30738,30693,30649,30604,30560,
        30515,30471,30426,30382,30337,30293,30248,30204,
        30159,30114,30070,30025,29980,29936,29891,29846,
        29801,29757,29712,29667,29622,29577,29533,29488,
        29443,29398,29353,29308,29263,29218,29173,29128,
        29083,29038,28993,28948,28903,28858,28812,28767,
        28722,28677,28632,28586,28541,28496,28451,28405,
        28360,28315,28269,28224,28179,28133,28088,28042,
        27997,27952,27906,27861,27815,27770,27724,27678,
        27633,27587,27542,27496,27450,27405,27359,27313,
        27268,27222,27176,27131,27085,27039,26993,26947,
        26902,26856,26810,26764,26718,26672,26626,26580,
        26534,26488,26442,26396,26350,26304,26258,26212,
        26166,26120,26074,26028,25982,25936,25889,25843,
        25797,25751,25705,25658,25612,25566,25520,25473,
        25427,25381,25334,25288,25241,25195,25149,25102,
        25056,25009,24963,24916,24870,24823,24777,24730,
        24684,24637,24591,24544,24497,24451,24404,24357,
        24311,24264,24217,24171,24124,24077,24030,23984,
        23937,23890,23843,23796,23750,23703,23656,23609,
        23562,23515,23468,23421,23374,23327,23280,23233,
        23186,23139,23092,23045,22998,22951,22904,22857,
        22810,22763,22716,22668,22621,22574,22527,22480,
        22433,22385,22338,22291,22243,22196,22149,22102,
        22054,22007,21960,21912,21865,21817,21770,21723,
        21675,21628,21580,21533,21485,21438,21390,21343,
        21295,21248,21200,21153,21105,21057,21010,20962,
        20915,20867,20819,20772,20724,20676,20629,20581,
        20533,20485,20438,20390,20342,20294,20246,20199,
        20151,20103,20055,20007,19959,19912,19864,19816,
        19768,19720,19672,19624,19576,19528,19480,19432,
        19384,19336,19288,19240,19192,19144,19096,19048,
        19000,18951,18903,18855,18807,18759,18711,18663,
        18614,18566,18518,18470,18421,18373,18325,18277,
        18228,18180,18132,18084,18035,17987,17939,17890,
        17842,17793,17745,17697,17648,17600,17551,17503,
        17455,17406,17358,17309,17261,17212,17164,17115,
        17067,17018,16970,16921,16872,16824,16775,16727,
        16678,16629,16581,16532,16484,16435,16386,16338,
        16289,16240,16191,16143,16094,16045,15997,15948,
        15899,15850,15802,15753,15704,15655,15606,15557,
        15509,15460,15411,15362,15313,15264,15215,15167,
        15118,15069,15020,14971,14922,14873,14824,14775,
        14726,14677,14628,14579,14530,14481,14432,14383,
        14334,14285,14236,14187,14138,14089,14040,13990,
        13941,13892,13843,13794,13745,13696,13646,13597,
        13548,13499,13450,13401,13351,13302,13253,13204,
        13154,13105,13056,13007,12957,12908,12859,12810,
        12760,12711,12662,12612,12563,12514,12464,12415,
        12366,12316,12267,12218,12168,12119,12069,12020,
        11970,11921,11872,11822,11773,11723,11674,11624,
        11575,11525,11476,11426,11377,11327,11278,11228,
        11179,11129,11080,11030,10981,10931,10882,10832,
        10782,10733,10683,10634,10584,10534,10485,10435,
        10386,10336,10286,10237,10187,10137,10088,10038,
        9988,9939,9889,9839,9790,9740,9690,9640,
        9591,9541,9491,9442,9392,9342,9292,9243,
        9193,9143,9093,9043,8994,8944,8894,8844,
        8794,8745,8695,8645,8595,8545,8496,8446,
        8396,8346,8296,8246,8196,8147,8097,8047,
        7997,7947,7897,7847,7797,7747,7697,7648,
        7598,7548,7498,7448,7398,7348,7298,7248,
        7198,7148,7098,7048,6998,6948,6898,6848,
        6798,6748,6698,6648,6598,6548,6498,6448,
        6398,6348,6298,6248,6198,6148,6098,6048,
        5998,5948,5898,5848,5798,5748,5697,5647,
        5597,5547,5497,5447,5397,5347,5297,5247,
        5197,5146,5096,5046,4996,4946,4896,4846,
        4796,4745,4695,4645,4595,4545,4495,4445,
        4394,4344,4294,4244,4194,4144,4093,4043,
        3993,3943,3893,3843,3792,3742,3692,3642,
        3592,3541,3491,3441,3391,3341,3291,3240,
        3190,3140,3090,3039,2989,2939,2889,2839,
        2788,2738,2688,2638,2587,2537,2487,2437,
        2387,2336,2286,2236,2186,2135,2085,2035,
        1985,1934,1884,1834,1784,1733,1683,1633,
        1583,1532,1482,1432,1382,1331,1281,1231,
        1181,1130,1080,1030,980,929,879,829,
        779,728,678,628,578,527,477,427,
        376,326,276,226,175,125,75,25,
        -25,-75,-125,-175,-226,-276,-326,-376,
        -427,-477,-527,-578,-628,-678,-728,-779,
        -829,-879,-929,-980,-1030,-1080,-1130,-1181,
        -1231,-1281,-1331,-1382,-1432,-1482,-1532,-1583,
        -1633,-1683,-1733,-1784,-1834,-1884,-1934,-1985,
        -2035,-2085,-2135,-2186,-2236,-2286,-2336,-2387,
        -2437,-2487,-2537,-2588,-2638,-2688,-2738,-2788,
        -2839,-2889,-2939,-2989,-3039,-3090,-3140,-3190,
        -3240,-3291,-3341,-3391,-3441,-3491,-3541,-3592,
        -3642,-3692,-3742,-3792,-3843,-3893,-3943,-3993,
        -4043,-4093,-4144,-4194,-4244,-4294,-4344,-4394,
        -4445,-4495,-4545,-4595,-4645,-4695,-4745,-4796,
        -4846,-4896,-4946,-4996,-5046,-5096,-5146,-5197,
        -5247,-5297,-5347,-5397,-5447,-5497,-5547,-5597,
        -5647,-5697,-5748,-5798,-5848,-5898,-5948,-5998,
        -6048,-6098,-6148,-6198,-6248,-6298,-6348,-6398,
        -6448,-6498,-6548,-6598,-6648,-6698,-6748,-6798,
        -6848,-6898,-6948,-6998,-7048,-7098,-7148,-7198,
        -7248,-7298,-7348,-7398,-7448,-7498,-7548,-7598,
        -7648,-7697,-7747,-7797,-7847,-7897,-7947,-7997,
        -8047,-8097,-8147,-8196,-8246,-8296,-8346,-8396,
        -8446,-8496,-8545,-8595,-8645,-8695,-8745,-8794,
        -8844,-8894,-8944,-8994,-9043,-9093,-9143,-9193,
        -9243,-9292,-9342,-9392,-9442,-9491,-9541,-9591,
        -9640,-9690,-9740,-9790,-9839,-9889,-9939,-9988,
        -10038,-10088,-10137,-10187,-10237,-10286,-10336,-10386,
        -10435,-10485,-10534,-10584,-10634,-10683,-10733,-10782,
        -10832,-10882,-10931,-10981,-11030,-11080,-11129,-11179,
        -11228,-11278,-11327,-11377,-11426,-11476,-11525,-11575,
        -11624,-11674,-11723,-11773,-11822,-11872,-11921,-11970,
        -12020,-12069,-12119,-12168,-12218,-12267,-12316,-12366,
        -12415,-12464,-12514,-12563,-12612,-12662,-12711,-12760,
        -12810,-12859,-12908,-12957,-13007,-13056,-13105,-13154,
        -13204,-13253,-13302,-13351,-13401,-13450,-13499,-13548,
        -13597,-13647,-13696,-13745,-13794,-13843,-13892,-13941,
        -13990,-14040,-14089,-14138,-14187,-14236,-14285,-14334,
        -14383,-14432,-14481,-14530,-14579,-14628,-14677,-14726,
        -14775,-14824,-14873,-14922,-14971,-15020,-15069,-15118,
        -15167,-15215,-15264,-15313,-15362,-15411,-15460,-15509,
        -15557,-15606,-15655,-15704,-15753,-15802,-15850,-15899,
        -15948,-15997,-16045,-16094,-16143,-16191,-16240,-16289,
        -16338,-16386,-16435,-16484,-16532,-16581,-16629,-16678,
        -16727,-16775,-16824,-16872,-16921,-16970,-17018,-17067,
        -17115,-17164,-17212,-17261,-17309,-17358,-17406,-17455,
        -17503,-17551,-17600,-17648,-17697,-17745,-17793,-17842,
        -17890,-17939,-17987,-18035,-18084,-18132,-18180,-18228,
        -18277,-18325,-18373,-18421,-18470,-18518,-18566,-18614,
        -18663,-18711,-18759,-18807,-18855,-18903,-18951,-19000,
        -19048,-19096,-19144,-19192,-19240,-19288,-19336,-19384,
        -19432,-19480,-19528,-19576,-19624,-19672,-19720,-19768,
        -19816,-19864,-19912,-19959,-20007,-20055,-20103,-20151,
        -20199,-20246,-20294,-20342,-20390,-20438,-20485,-20533,
        -20581,-20629,-20676,-20724,-20772,-20819,-20867,-20915,
        -20962,-21010,-21057,-21105,-21153,-21200,-21248,-21295,
        -21343,-21390,-21438,-21485,-21533,-21580,-21628,-21675,
        -21723,-21770,-21817,-21865,-21912,-21960,-22007,-22054,
        -22102,-22149,-22196,-22243,-22291,-22338,-22385,-22433,
        -22480,-22527,-22574,-22621,-22668,-22716,-22763,-22810,
        -22857,-22904,-22951,-22998,-23045,-23092,-23139,-23186,
        -23233,-23280,-23327,-23374,-23421,-23468,-23515,-23562,
        -23609,-23656,-23703,-23750,-23796,-23843,-23890,-23937,
        -23984,-24030,-24077,-24124,-24171,-24217,-24264,-24311,
        -24357,-24404,-24451,-24497,-24544,-24591,-24637,-24684,
        -24730,-24777,-24823,-24870,-24916,-24963,-25009,-25056,
        -25102,-25149,-25195,-25241,-25288,-25334,-25381,-25427,
        -25473,-25520,-25566,-25612,-25658,-25705,-25751,-25797,
        -25843,-25889,-25936,-25982,-26028,-26074,-26120,-26166,
        -26212,-26258,-26304,-26350,-26396,-26442,-26488,-26534,
        -26580,-26626,-26672,-26718,-26764,-26810,-26856,-26902,
        -26947,-26993,-27039,-27085,-27131,-27176,-27222,-27268,
        -27313,-27359,-27405,-27450,-27496,-27542,-27587,-27633,
        -27678,-27724,-27770,-27815,-27861,-27906,-27952,-27997,
        -28042,-28088,-28133,-28179,-28224,-28269,-28315,-28360,
        -28405,-28451,-28496,-28541,-28586,-28632,-28677,-28722,
        -28767,-28812,-28858,-28903,-28948,-28993,-29038,-29083,
        -29128,-29173,-29218,-29263,-29308,-29353,-29398,-29443,
        -29488,-29533,-29577,-29622,-29667,-29712,-29757,-29801,
        -29846,-29891,-29936,-29980,-30025,-30070,-30114,-30159,
        -30204,-30248,-30293,-30337,-30382,-30426,-30471,-30515,
        -30560,-30604,-30649,-30693,-30738,-30782,-30826,-30871,
        -30915,-30959,-31004,-31048,-31092,-31136,-31181,-31225,
        -31269,-31313,-31357,-31402,-31446,-31490,-31534,-31578,
        -31622,-31666,-31710,-31754,-31798,-31842,-31886,-31930,
        -31974,-32017,-32061,-32105,-32149,-32193,-32236,-32280,
        -32324,-32368,-32411,-32455,-32499,-32542,-32586,-32630,
        -32673,-32717,-32760,-32804,-32847,-32891,-32934,-32978,
        -33021,-33065,-33108,-33151,-33195,-33238,-33281,-33325,
        -33368,-33411,-33454,-33498,-33541,-33584,-33627,-33670,
        -33713,-33756,-33799,-33843,-33886,-33929,-33972,-34015,
        -34057,-34100,-34143,-34186,-34229,-34272,-34315,-34358,
        -34400,-34443,-34486,-34529,-34571,-34614,-34657,-34699,
        -34742,-34785,-34827,-34870,-34912,-34955,-34997,-35040,
        -35082,-35125,-35167,-35210,-35252,-35294,-35337,-35379,
        -35421,-35464,-35506,-35548,-35590,-35633,-35675,-35717,
        -35759,-35801,-35843,-35885,-35927,-35969,-36011,-36053,
        -36095,-36137,-36179,-36221,-36263,-36305,-36347,-36388,
        -36430,-36472,-36514,-36555,-36597,-36639,-36681,-36722,
        -36764,-36805,-36847,-36889,-36930,-36972,-37013,-37055,
        -37096,-37137,-37179,-37220,-37262,-37303,-37344,-37386,
        -37427,-37468,-37509,-37551,-37592,-37633,-37674,-37715,
        -37756,-37797,-37838,-37879,-37920,-37961,-38002,-38043,
        -38084,-38125,-38166,-38207,-38248,-38288,-38329,-38370,
        -38411,-38451,-38492,-38533,-38573,-38614,-38655,-38695,
        -38736,-38776,-38817,-38857,-38898,-38938,-38979,-39019,
        -39059,-39100,-39140,-39180,-39221,-39261,-39301,-39341,
        -39382,-39422,-39462,-39502,-39542,-39582,-39622,-39662,
        -39702,-39742,-39782,-39822,-39862,-39902,-39942,-39982,
        -40021,-40061,-40101,-40141,-40180,-40220,-40260,-40299,
        -40339,-40379,-40418,-40458,-40497,-40537,-40576,-40616,
        -40655,-40695,-40734,-40773,-40813,-40852,-40891,-40931,
        -40970,-41009,-41048,-41087,-41127,-41166,-41205,-41244,
        -41283,-41322,-41361,-41400,-41439,-41478,-41517,-41556,
        -41595,-41633,-41672,-41711,-41750,-41788,-41827,-41866,
        -41904,-41943,-41982,-42020,-42059,-42097,-42136,-42174,
        -42213,-42251,-42290,-42328,-42366,-42405,-42443,-42481,
        -42520,-42558,-42596,-42634,-42672,-42711,-42749,-42787,
        -42825,-42863,-42901,-42939,-42977,-43015,-43053,-43091,
        -43128,-43166,-43204,-43242,-43280,-43317,-43355,-43393,
        -43430,-43468,-43506,-43543,-43581,-43618,-43656,-43693,
        -43731,-43768,-43806,-43843,-43880,-43918,-43955,-43992,
        -44029,-44067,-44104,-44141,-44178,-44215,-44252,-44289,
        -44326,-44363,-44400,-44437,-44474,-44511,-44548,-44585,
        -44622,-44659,-44695,-44732,-44769,-44806,-44842,-44879,
        -44915,-44952,-44989,-45025,-45062,-45098,-45135,-45171,
        -45207,-45244,-45280,-45316,-45353,-45389,-45425,-45462,
        -45498,-45534,-45570,-45606,-45642,-45678,-45714,-45750,
        -45786,-45822,-45858,-45894,-45930,-45966,-46002,-46037,
        -46073,-46109,-46145,-46180,-46216,-46252,-46287,-46323,
        -46358,-46394,-46429,-46465,-46500,-46536,-46571,-46606,
        -46642,-46677,-46712,-46747,-46783,-46818,-46853,-46888,
        -46923,-46958,-46993,-47028,-47063,-47098,-47133,-47168,
        -47203,-47238,-47273,-47308,-47342,-47377,-47412,-47446,
        -47481,-47516,-47550,-47585,-47619,-47654,-47688,-47723,
        -47757,-47792,-47826,-47860,-47895,-47929,-47963,-47998,
        -48032,-48066,-48100,-48134,-48168,-48202,-48236,-48271,
        -48304,-48338,-48372,-48406,-48440,-48474,-48508,-48542,
        -48575,-48609,-48643,-48676,-48710,-48744,-48777,-48811,
        -48844,-48878,-48911,-48945,-48978,-49012,-49045,-49078,
        -49112,-49145,-49178,-49211,-49244,-49278,-49311,-49344,
        -49377,-49410,-49443,-49476,-49509,-49542,-49575,-49608,
        -49640,-49673,-49706,-49739,-49771,-49804,-49837,-49869,
        -49902,-49935,-49967,-50000,-50032,-50065,-50097,-50129,
        -50162,-50194,-50226,-50259,-50291,-50323,-50355,-50387,
        -50420,-50452,-50484,-50516,-50548,-50580,-50612,-50644,
        -50675,-50707,-50739,-50771,-50803,-50834,-50866,-50898,
        -50929,-50961,-50993,-51024,-51056,-51087,-51119,-51150,
        -51182,-51213,-51244,-51276,-51307,-51338,-51369,-51401,
        -51432,-51463,-51494,-51525,-51556,-51587,-51618,-51649,
        -51680,-51711,-51742,-51773,-51803,-51834,-51865,-51896,
        -51926,-51957,-51988,-52018,-52049,-52079,-52110,-52140,
        -52171,-52201,-52231,-52262,-52292,-52322,-52353,-52383,
        -52413,-52443,-52473,-52503,-52534,-52564,-52594,-52624,
        -52653,-52683,-52713,-52743,-52773,-52803,-52832,-52862,
        -52892,-52922,-52951,-52981,-53010,-53040,-53069,-53099,
        -53128,-53158,-53187,-53216,-53246,-53275,-53304,-53334,
        -53363,-53392,-53421,-53450,-53479,-53508,-53537,-53566,
        -53595,-53624,-53653,-53682,-53711,-53739,-53768,-53797,
        -53826,-53854,-53883,-53911,-53940,-53969,-53997,-54026,
        -54054,-54082,-54111,-54139,-54167,-54196,-54224,-54252,
        -54280,-54308,-54337,-54365,-54393,-54421,-54449,-54477,
        -54505,-54533,-54560,-54588,-54616,-54644,-54672,-54699,
        -54727,-54755,-54782,-54810,-54837,-54865,-54892,-54920,
        -54947,-54974,-55002,-55029,-55056,-55084,-55111,-55138,
        -55165,-55192,-55219,-55246,-55274,-55300,-55327,-55354,
        -55381,-55408,-55435,-55462,-55489,-55515,-55542,-55569,
        -55595,-55622,-55648,-55675,-55701,-55728,-55754,-55781,
        -55807,-55833,-55860,-55886,-55912,-55938,-55965,-55991,
        -56017,-56043,-56069,-56095,-56121,-56147,-56173,-56199,
        -56225,-56250,-56276,-56302,-56328,-56353,-56379,-56404,
        -56430,-56456,-56481,-56507,-56532,-56557,-56583,-56608,
        -56633,-56659,-56684,-56709,-56734,-56760,-56785,-56810,
        -56835,-56860,-56885,-56910,-56935,-56959,-56984,-57009,
        -57034,-57059,-57083,-57108,-57133,-57157,-57182,-57206,
        -57231,-57255,-57280,-57304,-57329,-57353,-57377,-57402,
        -57426,-57450,-57474,-57498,-57522,-57546,-57570,-57594,
        -57618,-57642,-57666,-57690,-57714,-57738,-57762,-57785,
        -57809,-57833,-57856,-57880,-57903,-57927,-57950,-57974,
        -57997,-58021,-58044,-58067,-58091,-58114,-58137,-58160,
        -58183,-58207,-58230,-58253,-58276,-58299,-58322,-58345,
        -58367,-58390,-58413,-58436,-58459,-58481,-58504,-58527,
        -58549,-58572,-58594,-58617,-58639,-58662,-58684,-58706,
        -58729,-58751,-58773,-58795,-58818,-58840,-58862,-58884,
        -58906,-58928,-58950,-58972,-58994,-59016,-59038,-59059,
        -59081,-59103,-59125,-59146,-59168,-59190,-59211,-59233,
        -59254,-59276,-59297,-59318,-59340,-59361,-59382,-59404,
        -59425,-59446,-59467,-59488,-59509,-59530,-59551,-59572,
        -59593,-59614,-59635,-59656,-59677,-59697,-59718,-59739,
        -59759,-59780,-59801,-59821,-59842,-59862,-59883,-59903,
        -59923,-59944,-59964,-59984,-60004,-60025,-60045,-60065,
        -60085,-60105,-60125,-60145,-60165,-60185,-60205,-60225,
        -60244,-60264,-60284,-60304,-60323,-60343,-60363,-60382,
        -60402,-60421,-60441,-60460,-60479,-60499,-60518,-60537,
        -60556,-60576,-60595,-60614,-60633,-60652,-60671,-60690,
        -60709,-60728,-60747,-60766,-60785,-60803,-60822,-60841,
        -60859,-60878,-60897,-60915,-60934,-60952,-60971,-60989,
        -61007,-61026,-61044,-61062,-61081,-61099,-61117,-61135,
        -61153,-61171,-61189,-61207,-61225,-61243,-61261,-61279,
        -61297,-61314,-61332,-61350,-61367,-61385,-61403,-61420,
        -61438,-61455,-61473,-61490,-61507,-61525,-61542,-61559,
        -61577,-61594,-61611,-61628,-61645,-61662,-61679,-61696,
        -61713,-61730,-61747,-61764,-61780,-61797,-61814,-61831,
        -61847,-61864,-61880,-61897,-61913,-61930,-61946,-61963,
        -61979,-61995,-62012,-62028,-62044,-62060,-62076,-62092,
        -62108,-62125,-62141,-62156,-62172,-62188,-62204,-62220,
        -62236,-62251,-62267,-62283,-62298,-62314,-62329,-62345,
        -62360,-62376,-62391,-62407,-62422,-62437,-62453,-62468,
        -62483,-62498,-62513,-62528,-62543,-62558,-62573,-62588,
        -62603,-62618,-62633,-62648,-62662,-62677,-62692,-62706,
        -62721,-62735,-62750,-62764,-62779,-62793,-62808,-62822,
        -62836,-62850,-62865,-62879,-62893,-62907,-62921,-62935,
        -62949,-62963,-62977,-62991,-63005,-63019,-63032,-63046,
        -63060,-63074,-63087,-63101,-63114,-63128,-63141,-63155,
        -63168,-63182,-63195,-63208,-63221,-63235,-63248,-63261,
        -63274,-63287,-63300,-63313,-63326,-63339,-63352,-63365,
        -63378,-63390,-63403,-63416,-63429,-63441,-63454,-63466,
        -63479,-63491,-63504,-63516,-63528,-63541,-63553,-63565,
        -63578,-63590,-63602,-63614,-63626,-63638,-63650,-63662,
        -63674,-63686,-63698,-63709,-63721,-63733,-63745,-63756,
        -63768,-63779,-63791,-63803,-63814,-63825,-63837,-63848,
        -63859,-63871,-63882,-63893,-63904,-63915,-63927,-63938,
        -63949,-63960,-63971,-63981,-63992,-64003,-64014,-64025,
        -64035,-64046,-64057,-64067,-64078,-64088,-64099,-64109,
        -64120,-64130,-64140,-64151,-64161,-64171,-64181,-64192,
        -64202,-64212,-64222,-64232,-64242,-64252,-64261,-64271,
        -64281,-64291,-64301,-64310,-64320,-64330,-64339,-64349,
        -64358,-64368,-64377,-64387,-64396,-64405,-64414,-64424,
        -64433,-64442,-64451,-64460,-64469,-64478,-64487,-64496,
        -64505,-64514,-64523,-64532,-64540,-64549,-64558,-64566,
        -64575,-64584,-64592,-64601,-64609,-64617,-64626,-64634,
        -64642,-64651,-64659,-64667,-64675,-64683,-64691,-64699,
        -64707,-64715,-64723,-64731,-64739,-64747,-64754,-64762,
        -64770,-64777,-64785,-64793,-64800,-64808,-64815,-64822,
        -64830,-64837,-64844,-64852,-64859,-64866,-64873,-64880,
        -64887,-64895,-64902,-64908,-64915,-64922,-64929,-64936,
        -64943,-64949,-64956,-64963,-64969,-64976,-64982,-64989,
        -64995,-65002,-65008,-65015,-65021,-65027,-65033,-65040,
        -65046,-65052,-65058,-65064,-65070,-65076,-65082,-65088,
        -65094,-65099,-65105,-65111,-65117,-65122,-65128,-65133,
        -65139,-65144,-65150,-65155,-65161,-65166,-65171,-65177,
        -65182,-65187,-65192,-65197,-65202,-65207,-65212,-65217,
        -65222,-65227,-65232,-65237,-65242,-65246,-65251,-65256,
        -65260,-65265,-65270,-65274,-65279,-65283,-65287,-65292,
        -65296,-65300,-65305,-65309,-65313,-65317,-65321,-65325,
        -65329,-65333,-65337,-65341,-65345,-65349,-65352,-65356,
        -65360,-65363,-65367,-65371,-65374,-65378,-65381,-65385,
        -65388,-65391,-65395,-65398,-65401,-65404,-65408,-65411,
        -65414,-65417,-65420,-65423,-65426,-65429,-65431,-65434,
        -65437,-65440,-65442,-65445,-65448,-65450,-65453,-65455,
        -65458,-65460,-65463,-65465,-65467,-65470,-65472,-65474,
        -65476,-65478,-65480,-65482,-65484,-65486,-65488,-65490,
        -65492,-65494,-65496,-65497,-65499,-65501,-65502,-65504,
        -65505,-65507,-65508,-65510,-65511,-65513,-65514,-65515,
        -65516,-65518,-65519,-65520,-65521,-65522,-65523,-65524,
        -65525,-65526,-65527,-65527,-65528,-65529,-65530,-65530,
        -65531,-65531,-65532,-65532,-65533,-65533,-65534,-65534,
        -65534,-65535,-65535,-65535,-65535,-65535,-65535,-65535,
        -65535,-65535,-65535,-65535,-65535,-65535,-65535,-65534,
        -65534,-65534,-65533,-65533,-65532,-65532,-65531,-65531,
        -65530,-65530,-65529,-65528,-65527,-65527,-65526,-65525,
        -65524,-65523,-65522,-65521,-65520,-65519,-65518,-65516,
        -65515,-65514,-65513,-65511,-65510,-65508,-65507,-65505,
        -65504,-65502,-65501,-65499,-65497,-65496,-65494,-65492,
        -65490,-65488,-65486,-65484,-65482,-65480,-65478,-65476,
        -65474,-65472,-65470,-65467,-65465,-65463,-65460,-65458,
        -65455,-65453,-65450,-65448,-65445,-65442,-65440,-65437,
        -65434,-65431,-65429,-65426,-65423,-65420,-65417,-65414,
        -65411,-65408,-65404,-65401,-65398,-65395,-65391,-65388,
        -65385,-65381,-65378,-65374,-65371,-65367,-65363,-65360,
        -65356,-65352,-65349,-65345,-65341,-65337,-65333,-65329,
        -65325,-65321,-65317,-65313,-65309,-65305,-65300,-65296,
        -65292,-65287,-65283,-65279,-65274,-65270,-65265,-65260,
        -65256,-65251,-65246,-65242,-65237,-65232,-65227,-65222,
        -65217,-65212,-65207,-65202,-65197,-65192,-65187,-65182,
        -65177,-65171,-65166,-65161,-65155,-65150,-65144,-65139,
        -65133,-65128,-65122,-65117,-65111,-65105,-65099,-65094,
        -65088,-65082,-65076,-65070,-65064,-65058,-65052,-65046,
        -65040,-65033,-65027,-65021,-65015,-65008,-65002,-64995,
        -64989,-64982,-64976,-64969,-64963,-64956,-64949,-64943,
        -64936,-64929,-64922,-64915,-64908,-64902,-64895,-64887,
        -64880,-64873,-64866,-64859,-64852,-64844,-64837,-64830,
        -64822,-64815,-64808,-64800,-64793,-64785,-64777,-64770,
        -64762,-64754,-64747,-64739,-64731,-64723,-64715,-64707,
        -64699,-64691,-64683,-64675,-64667,-64659,-64651,-64642,
        -64634,-64626,-64617,-64609,-64601,-64592,-64584,-64575,
        -64566,-64558,-64549,-64540,-64532,-64523,-64514,-64505,
        -64496,-64487,-64478,-64469,-64460,-64451,-64442,-64433,
        -64424,-64414,-64405,-64396,-64387,-64377,-64368,-64358,
        -64349,-64339,-64330,-64320,-64310,-64301,-64291,-64281,
        -64271,-64261,-64252,-64242,-64232,-64222,-64212,-64202,
        -64192,-64181,-64171,-64161,-64151,-64140,-64130,-64120,
        -64109,-64099,-64088,-64078,-64067,-64057,-64046,-64035,
        -64025,-64014,-64003,-63992,-63981,-63971,-63960,-63949,
        -63938,-63927,-63915,-63904,-63893,-63882,-63871,-63859,
        -63848,-63837,-63825,-63814,-63803,-63791,-63779,-63768,
        -63756,-63745,-63733,-63721,-63709,-63698,-63686,-63674,
        -63662,-63650,-63638,-63626,-63614,-63602,-63590,-63578,
        -63565,-63553,-63541,-63528,-63516,-63504,-63491,-63479,
        -63466,-63454,-63441,-63429,-63416,-63403,-63390,-63378,
        -63365,-63352,-63339,-63326,-63313,-63300,-63287,-63274,
        -63261,-63248,-63235,-63221,-63208,-63195,-63182,-63168,
        -63155,-63141,-63128,-63114,-63101,-63087,-63074,-63060,
        -63046,-63032,-63019,-63005,-62991,-62977,-62963,-62949,
        -62935,-62921,-62907,-62893,-62879,-62865,-62850,-62836,
        -62822,-62808,-62793,-62779,-62764,-62750,-62735,-62721,
        -62706,-62692,-62677,-62662,-62648,-62633,-62618,-62603,
        -62588,-62573,-62558,-62543,-62528,-62513,-62498,-62483,
        -62468,-62453,-62437,-62422,-62407,-62391,-62376,-62360,
        -62345,-62329,-62314,-62298,-62283,-62267,-62251,-62236,
        -62220,-62204,-62188,-62172,-62156,-62141,-62125,-62108,
        -62092,-62076,-62060,-62044,-62028,-62012,-61995,-61979,
        -61963,-61946,-61930,-61913,-61897,-61880,-61864,-61847,
        -61831,-61814,-61797,-61780,-61764,-61747,-61730,-61713,
        -61696,-61679,-61662,-61645,-61628,-61611,-61594,-61577,
        -61559,-61542,-61525,-61507,-61490,-61473,-61455,-61438,
        -61420,-61403,-61385,-61367,-61350,-61332,-61314,-61297,
        -61279,-61261,-61243,-61225,-61207,-61189,-61171,-61153,
        -61135,-61117,-61099,-61081,-61062,-61044,-61026,-61007,
        -60989,-60971,-60952,-60934,-60915,-60897,-60878,-60859,
        -60841,-60822,-60803,-60785,-60766,-60747,-60728,-60709,
        -60690,-60671,-60652,-60633,-60614,-60595,-60576,-60556,
        -60537,-60518,-60499,-60479,-60460,-60441,-60421,-60402,
        -60382,-60363,-60343,-60323,-60304,-60284,-60264,-60244,
        -60225,-60205,-60185,-60165,-60145,-60125,-60105,-60085,
        -60065,-60045,-60025,-60004,-59984,-59964,-59944,-59923,
        -59903,-59883,-59862,-59842,-59821,-59801,-59780,-59759,
        -59739,-59718,-59697,-59677,-59656,-59635,-59614,-59593,
        -59572,-59551,-59530,-59509,-59488,-59467,-59446,-59425,
        -59404,-59382,-59361,-59340,-59318,-59297,-59276,-59254,
        -59233,-59211,-59189,-59168,-59146,-59125,-59103,-59081,
        -59059,-59038,-59016,-58994,-58972,-58950,-58928,-58906,
        -58884,-58862,-58840,-58818,-58795,-58773,-58751,-58729,
        -58706,-58684,-58662,-58639,-58617,-58594,-58572,-58549,
        -58527,-58504,-58481,-58459,-58436,-58413,-58390,-58367,
        -58345,-58322,-58299,-58276,-58253,-58230,-58207,-58183,
        -58160,-58137,-58114,-58091,-58067,-58044,-58021,-57997,
        -57974,-57950,-57927,-57903,-57880,-57856,-57833,-57809,
        -57785,-57762,-57738,-57714,-57690,-57666,-57642,-57618,
        -57594,-57570,-57546,-57522,-57498,-57474,-57450,-57426,
        -57402,-57377,-57353,-57329,-57304,-57280,-57255,-57231,
        -57206,-57182,-57157,-57133,-57108,-57083,-57059,-57034,
        -57009,-56984,-56959,-56935,-56910,-56885,-56860,-56835,
        -56810,-56785,-56760,-56734,-56709,-56684,-56659,-56633,
        -56608,-56583,-56557,-56532,-56507,-56481,-56456,-56430,
        -56404,-56379,-56353,-56328,-56302,-56276,-56250,-56225,
        -56199,-56173,-56147,-56121,-56095,-56069,-56043,-56017,
        -55991,-55965,-55938,-55912,-55886,-55860,-55833,-55807,
        -55781,-55754,-55728,-55701,-55675,-55648,-55622,-55595,
        -55569,-55542,-55515,-55489,-55462,-55435,-55408,-55381,
        -55354,-55327,-55300,-55274,-55246,-55219,-55192,-55165,
        -55138,-55111,-55084,-55056,-55029,-55002,-54974,-54947,
        -54920,-54892,-54865,-54837,-54810,-54782,-54755,-54727,
        -54699,-54672,-54644,-54616,-54588,-54560,-54533,-54505,
        -54477,-54449,-54421,-54393,-54365,-54337,-54308,-54280,
        -54252,-54224,-54196,-54167,-54139,-54111,-54082,-54054,
        -54026,-53997,-53969,-53940,-53911,-53883,-53854,-53826,
        -53797,-53768,-53739,-53711,-53682,-53653,-53624,-53595,
        -53566,-53537,-53508,-53479,-53450,-53421,-53392,-53363,
        -53334,-53304,-53275,-53246,-53216,-53187,-53158,-53128,
        -53099,-53069,-53040,-53010,-52981,-52951,-52922,-52892,
        -52862,-52832,-52803,-52773,-52743,-52713,-52683,-52653,
        -52624,-52594,-52564,-52534,-52503,-52473,-52443,-52413,
        -52383,-52353,-52322,-52292,-52262,-52231,-52201,-52171,
        -52140,-52110,-52079,-52049,-52018,-51988,-51957,-51926,
        -51896,-51865,-51834,-51803,-51773,-51742,-51711,-51680,
        -51649,-51618,-51587,-51556,-51525,-51494,-51463,-51432,
        -51401,-51369,-51338,-51307,-51276,-51244,-51213,-51182,
        -51150,-51119,-51087,-51056,-51024,-50993,-50961,-50929,
        -50898,-50866,-50834,-50803,-50771,-50739,-50707,-50675,
        -50644,-50612,-50580,-50548,-50516,-50484,-50452,-50420,
        -50387,-50355,-50323,-50291,-50259,-50226,-50194,-50162,
        -50129,-50097,-50065,-50032,-50000,-49967,-49935,-49902,
        -49869,-49837,-49804,-49771,-49739,-49706,-49673,-49640,
        -49608,-49575,-49542,-49509,-49476,-49443,-49410,-49377,
        -49344,-49311,-49278,-49244,-49211,-49178,-49145,-49112,
        -49078,-49045,-49012,-48978,-48945,-48911,-48878,-48844,
        -48811,-48777,-48744,-48710,-48676,-48643,-48609,-48575,
        -48542,-48508,-48474,-48440,-48406,-48372,-48338,-48305,
        -48271,-48237,-48202,-48168,-48134,-48100,-48066,-48032,
        -47998,-47963,-47929,-47895,-47860,-47826,-47792,-47757,
        -47723,-47688,-47654,-47619,-47585,-47550,-47516,-47481,
        -47446,-47412,-47377,-47342,-47307,-47273,-47238,-47203,
        -47168,-47133,-47098,-47063,-47028,-46993,-46958,-46923,
        -46888,-46853,-46818,-46783,-46747,-46712,-46677,-46642,
        -46606,-46571,-46536,-46500,-46465,-46429,-46394,-46358,
        -46323,-46287,-46251,-46216,-46180,-46145,-46109,-46073,
        -46037,-46002,-45966,-45930,-45894,-45858,-45822,-45786,
        -45750,-45714,-45678,-45642,-45606,-45570,-45534,-45498,
        -45462,-45425,-45389,-45353,-45316,-45280,-45244,-45207,
        -45171,-45135,-45098,-45062,-45025,-44989,-44952,-44915,
        -44879,-44842,-44806,-44769,-44732,-44695,-44659,-44622,
        -44585,-44548,-44511,-44474,-44437,-44400,-44363,-44326,
        -44289,-44252,-44215,-44178,-44141,-44104,-44067,-44029,
        -43992,-43955,-43918,-43880,-43843,-43806,-43768,-43731,
        -43693,-43656,-43618,-43581,-43543,-43506,-43468,-43430,
        -43393,-43355,-43317,-43280,-43242,-43204,-43166,-43128,
        -43091,-43053,-43015,-42977,-42939,-42901,-42863,-42825,
        -42787,-42749,-42711,-42672,-42634,-42596,-42558,-42520,
        -42481,-42443,-42405,-42366,-42328,-42290,-42251,-42213,
        -42174,-42136,-42097,-42059,-42020,-41982,-41943,-41904,
        -41866,-41827,-41788,-41750,-41711,-41672,-41633,-41595,
        -41556,-41517,-41478,-41439,-41400,-41361,-41322,-41283,
        -41244,-41205,-41166,-41127,-41087,-41048,-41009,-40970,
        -40931,-40891,-40852,-40813,-40773,-40734,-40695,-40655,
        -40616,-40576,-40537,-40497,-40458,-40418,-40379,-40339,
        -40299,-40260,-40220,-40180,-40141,-40101,-40061,-40021,
        -39982,-39942,-39902,-39862,-39822,-39782,-39742,-39702,
        -39662,-39622,-39582,-39542,-39502,-39462,-39422,-39382,
        -39341,-39301,-39261,-39221,-39180,-39140,-39100,-39059,
        -39019,-38979,-38938,-38898,-38857,-38817,-38776,-38736,
        -38695,-38655,-38614,-38573,-38533,-38492,-38451,-38411,
        -38370,-38329,-38288,-38248,-38207,-38166,-38125,-38084,
        -38043,-38002,-37961,-37920,-37879,-37838,-37797,-37756,
        -37715,-37674,-37633,-37592,-37550,-37509,-37468,-37427,
        -37386,-37344,-37303,-37262,-37220,-37179,-37137,-37096,
        -37055,-37013,-36972,-36930,-36889,-36847,-36805,-36764,
        -36722,-36681,-36639,-36597,-36556,-36514,-36472,-36430,
        -36388,-36347,-36305,-36263,-36221,-36179,-36137,-36095,
        -36053,-36011,-35969,-35927,-35885,-35843,-35801,-35759,
        -35717,-35675,-35633,-35590,-35548,-35506,-35464,-35421,
        -35379,-35337,-35294,-35252,-35210,-35167,-35125,-35082,
        -35040,-34997,-34955,-34912,-34870,-34827,-34785,-34742,
        -34699,-34657,-34614,-34571,-34529,-34486,-34443,-34400,
        -34358,-34315,-34272,-34229,-34186,-34143,-34100,-34057,
        -34015,-33972,-33929,-33886,-33843,-33799,-33756,-33713,
        -33670,-33627,-33584,-33541,-33498,-33454,-33411,-33368,
        -33325,-33281,-33238,-33195,-33151,-33108,-33065,-33021,
        -32978,-32934,-32891,-32847,-32804,-32760,-32717,-32673,
        -32630,-32586,-32542,-32499,-32455,-32411,-32368,-32324,
        -32280,-32236,-32193,-32149,-32105,-32061,-32017,-31974,
        -31930,-31886,-31842,-31798,-31754,-31710,-31666,-31622,
        -31578,-31534,-31490,-31446,-31402,-31357,-31313,-31269,
        -31225,-31181,-31136,-31092,-31048,-31004,-30959,-30915,
        -30871,-30826,-30782,-30738,-30693,-30649,-30604,-30560,
        -30515,-30471,-30426,-30382,-30337,-30293,-30248,-30204,
        -30159,-30114,-30070,-30025,-29980,-29936,-29891,-29846,
        -29801,-29757,-29712,-29667,-29622,-29577,-29533,-29488,
        -29443,-29398,-29353,-29308,-29263,-29218,-29173,-29128,
        -29083,-29038,-28993,-28948,-28903,-28858,-28812,-28767,
        -28722,-28677,-28632,-28586,-28541,-28496,-28451,-28405,
        -28360,-28315,-28269,-28224,-28179,-28133,-28088,-28042,
        -27997,-27952,-27906,-27861,-27815,-27770,-27724,-27678,
        -27633,-27587,-27542,-27496,-27450,-27405,-27359,-27313,
        -27268,-27222,-27176,-27131,-27085,-27039,-26993,-26947,
        -26902,-26856,-26810,-26764,-26718,-26672,-26626,-26580,
        -26534,-26488,-26442,-26396,-26350,-26304,-26258,-26212,
        -26166,-26120,-26074,-26028,-25982,-25936,-25889,-25843,
        -25797,-25751,-25705,-25658,-25612,-25566,-25520,-25473,
        -25427,-25381,-25334,-25288,-25241,-25195,-25149,-25102,
        -25056,-25009,-24963,-24916,-24870,-24823,-24777,-24730,
        -24684,-24637,-24591,-24544,-24497,-24451,-24404,-24357,
        -24311,-24264,-24217,-24171,-24124,-24077,-24030,-23984,
        -23937,-23890,-23843,-23796,-23750,-23703,-23656,-23609,
        -23562,-23515,-23468,-23421,-23374,-23327,-23280,-23233,
        -23186,-23139,-23092,-23045,-22998,-22951,-22904,-22857,
        -22810,-22763,-22716,-22668,-22621,-22574,-22527,-22480,
        -22432,-22385,-22338,-22291,-22243,-22196,-22149,-22102,
        -22054,-22007,-21960,-21912,-21865,-21817,-21770,-21723,
        -21675,-21628,-21580,-21533,-21485,-21438,-21390,-21343,
        -21295,-21248,-21200,-21153,-21105,-21057,-21010,-20962,
        -20915,-20867,-20819,-20772,-20724,-20676,-20629,-20581,
        -20533,-20485,-20438,-20390,-20342,-20294,-20246,-20199,
        -20151,-20103,-20055,-20007,-19959,-19912,-19864,-19816,
        -19768,-19720,-19672,-19624,-19576,-19528,-19480,-19432,
        -19384,-19336,-19288,-19240,-19192,-19144,-19096,-19048,
        -19000,-18951,-18903,-18855,-18807,-18759,-18711,-18663,
        -18614,-18566,-18518,-18470,-18421,-18373,-18325,-18277,
        -18228,-18180,-18132,-18084,-18035,-17987,-17939,-17890,
        -17842,-17793,-17745,-17697,-17648,-17600,-17551,-17503,
        -17455,-17406,-17358,-17309,-17261,-17212,-17164,-17115,
        -17067,-17018,-16970,-16921,-16872,-16824,-16775,-16727,
        -16678,-16629,-16581,-16532,-16484,-16435,-16386,-16338,
        -16289,-16240,-16191,-16143,-16094,-16045,-15997,-15948,
        -15899,-15850,-15802,-15753,-15704,-15655,-15606,-15557,
        -15509,-15460,-15411,-15362,-15313,-15264,-15215,-15167,
        -15118,-15069,-15020,-14971,-14922,-14873,-14824,-14775,
        -14726,-14677,-14628,-14579,-14530,-14481,-14432,-14383,
        -14334,-14285,-14236,-14187,-14138,-14089,-14040,-13990,
        -13941,-13892,-13843,-13794,-13745,-13696,-13647,-13597,
        -13548,-13499,-13450,-13401,-13351,-13302,-13253,-13204,
        -13154,-13105,-13056,-13007,-12957,-12908,-12859,-12810,
        -12760,-12711,-12662,-12612,-12563,-12514,-12464,-12415,
        -12366,-12316,-12267,-12217,-12168,-12119,-12069,-12020,
        -11970,-11921,-11872,-11822,-11773,-11723,-11674,-11624,
        -11575,-11525,-11476,-11426,-11377,-11327,-11278,-11228,
        -11179,-11129,-11080,-11030,-10981,-10931,-10882,-10832,
        -10782,-10733,-10683,-10634,-10584,-10534,-10485,-10435,
        -10386,-10336,-10286,-10237,-10187,-10137,-10088,-10038,
        -9988,-9939,-9889,-9839,-9790,-9740,-9690,-9640,
        -9591,-9541,-9491,-9442,-9392,-9342,-9292,-9243,
        -9193,-9143,-9093,-9043,-8994,-8944,-8894,-8844,
        -8794,-8745,-8695,-8645,-8595,-8545,-8496,-8446,
        -8396,-8346,-8296,-8246,-8196,-8147,-8097,-8047,
        -7997,-7947,-7897,-7847,-7797,-7747,-7697,-7648,
        -7598,-7548,-7498,-7448,-7398,-7348,-7298,-7248,
        -7198,-7148,-7098,-7048,-6998,-6948,-6898,-6848,
        -6798,-6748,-6698,-6648,-6598,-6548,-6498,-6448,
        -6398,-6348,-6298,-6248,-6198,-6148,-6098,-6048,
        -5998,-5948,-5898,-5848,-5798,-5747,-5697,-5647,
        -5597,-5547,-5497,-5447,-5397,-5347,-5297,-5247,
        -5197,-5146,-5096,-5046,-4996,-4946,-4896,-4846,
        -4796,-4745,-4695,-4645,-4595,-4545,-4495,-4445,
        -4394,-4344,-4294,-4244,-4194,-4144,-4093,-4043,
        -3993,-3943,-3893,-3843,-3792,-3742,-3692,-3642,
        -3592,-3541,-3491,-3441,-3391,-3341,-3291,-3240,
        -3190,-3140,-3090,-3039,-2989,-2939,-2889,-2839,
        -2788,-2738,-2688,-2638,-2588,-2537,-2487,-2437,
        -2387,-2336,-2286,-2236,-2186,-2135,-2085,-2035,
        -1985,-1934,-1884,-1834,-1784,-1733,-1683,-1633,
        -1583,-1532,-1482,-1432,-1382,-1331,-1281,-1231,
        -1181,-1130,-1080,-1030,-980,-929,-879,-829,
        -779,-728,-678,-628,-578,-527,-477,-427,
        -376,-326,-276,-226,-175,-125,-75,-25    
    };
    
    /* MAES: Java can't use that much direct init data in a single class (finesine alone is well beyond that)
     * so a first workaround is to generate the data procedurally.
     * If this proves to cause accuracy problems, an external data file could be used.
     * Another workaround is to define the int table in its own file and then import or "implement" it.
     */
    
 // Re-use data, is just PI/2 phase shift.
  public static final int[] finecosine=new int[FINEANGLES];

  /* MAES: Java can't use that much direct init data in a single class so a first workaround 
   * s to generate the data procedurally.
   * If this proves to cause accuracy problems, an external data file could be used.
   * Another workaround is to define the int table in its own file and then import 
   * or "implement" it.
   */

  static{
  System.arraycopy(finesine, FINEANGLES/4,finecosine, 0, FINEANGLES);
  }

  private SineCosine(){
      
  }
    
}

package data;

public enum mobjtype_t {
	    MT_PLAYER,
	    MT_POSSESSED,
	    MT_SHOTGUY,
	    MT_VILE,
	    MT_FIRE,
	    MT_UNDEAD,
	    MT_TRACER,
	    MT_SMOKE,
	    MT_FATSO,
	    MT_FATSHOT,
	    MT_CHAINGUY,
	    MT_TROOP,
	    MT_SERGEANT,
	    MT_SHADOWS,
	    MT_HEAD,
	    MT_BRUISER,
	    MT_BRUISERSHOT,
	    MT_KNIGHT,
	    MT_SKULL,
	    MT_SPIDER,
	    MT_BABY,
	    MT_CYBORG,
	    MT_PAIN,
	    MT_WOLFSS,
	    MT_KEEN,
	    MT_BOSSBRAIN,
	    MT_BOSSSPIT,
	    MT_BOSSTARGET,
	    MT_SPAWNSHOT,
	    MT_SPAWNFIRE,
	    MT_BARREL,
	    MT_TROOPSHOT,
	    MT_HEADSHOT,
	    MT_ROCKET,
	    MT_PLASMA,
	    MT_BFG,
	    MT_ARACHPLAZ,
	    MT_PUFF,
	    MT_BLOOD,
	    MT_TFOG,
	    MT_IFOG,
	    MT_TELEPORTMAN,
	    MT_EXTRABFG,
	    MT_MISC0,
	    MT_MISC1,
	    MT_MISC2,
	    MT_MISC3,
	    MT_MISC4,
	    MT_MISC5,
	    MT_MISC6,
	    MT_MISC7,
	    MT_MISC8,
	    MT_MISC9,
	    MT_MISC10,
	    MT_MISC11,
	    MT_MISC12,
	    MT_INV,
	    MT_MISC13,
	    MT_INS,
	    MT_MISC14,
	    MT_MISC15,
	    MT_MISC16,
	    MT_MEGA,
	    MT_CLIP,
	    MT_MISC17,
	    MT_MISC18,
	    MT_MISC19,
	    MT_MISC20,
	    MT_MISC21,
	    MT_MISC22,
	    MT_MISC23,
	    MT_MISC24,
	    MT_MISC25,
	    MT_CHAINGUN,
	    MT_MISC26,
	    MT_MISC27,
	    MT_MISC28,
	    MT_SHOTGUN,
	    MT_SUPERSHOTGUN,
	    MT_MISC29,
	    MT_MISC30,
	    MT_MISC31,
	    MT_MISC32,
	    MT_MISC33,
	    MT_MISC34,
	    MT_MISC35,
	    MT_MISC36,
	    MT_MISC37,
	    MT_MISC38,
	    MT_MISC39,
	    MT_MISC40,
	    MT_MISC41,
	    MT_MISC42,
	    MT_MISC43,
	    MT_MISC44,
	    MT_MISC45,
	    MT_MISC46,
	    MT_MISC47,
	    MT_MISC48,
	    MT_MISC49,
	    MT_MISC50,
	    MT_MISC51,
	    MT_MISC52,
	    MT_MISC53,
	    MT_MISC54,
	    MT_MISC55,
	    MT_MISC56,
	    MT_MISC57,
	    MT_MISC58,
	    MT_MISC59,
	    MT_MISC60,
	    MT_MISC61,
	    MT_MISC62,
	    MT_MISC63,
	    MT_MISC64,
	    MT_MISC65,
	    MT_MISC66,
	    MT_MISC67,
	    MT_MISC68,
	    MT_MISC69,
	    MT_MISC70,
	    MT_MISC71,
	    MT_MISC72,
	    MT_MISC73,
	    MT_MISC74,
	    MT_MISC75,
	    MT_MISC76,
	    MT_MISC77,
	    MT_MISC78,
	    MT_MISC79,
	    MT_MISC80,
	    MT_MISC81,
	    MT_MISC82,
	    MT_MISC83,
	    MT_MISC84,
	    MT_MISC85,
	    MT_MISC86,
	    NUMMOBJTYPES
	    };


package data;

import p.ActionType1;
import p.ActionType2;
import p.ActionTypeSS;
import doom.think_t;
import defines.statenum_t;
import static data.Defines.TIC_MUL;

public class state_t {

	public state_t(){
		
	}
       
        public state_t(spritenum_t sprite, int frame, int tics, think_t action,
            statenum_t nextstate, int misc1, int misc2) {
        this.sprite = sprite;
        this.frame = frame;
        this.tics = tics*TIC_MUL;
        this.action = action;
        this.nextstate = nextstate;
        this.misc1 = misc1;
        this.misc2 = misc2;
        }
        
        public spritenum_t   sprite;
        /** The frame should indicate which one of the frames available in the 
         *  available spritenum should be used. This can also be flagged with
         *  0x8000 indicating bright sprites.
         */
 
        public int          frame;
        public int          tics;
        //TODO: proper implementation of (*action)
        // MAES: was actionp_t... which is typedeffed to think_t anyway,
        // and this is the only place it's invoked explicitly.
        /** OK...this is the most infamous part of Doom to implement in Java.
         *  We can't have proper "function pointers" in java without either losing a LOT
         *  of speed (through reflection) or cluttering syntax and heap significantly
         *  (callback objects, which also need to be aware of context).
         *  Therefore, I decided to implement an "action dispatcher".
         *  This a
         *  
         */
        public think_t         action;
        public ActionType1 acp1;
        public ActionType2 acp2;
        public ActionTypeSS acpss;
        
        public statenum_t            nextstate;
        public int misc1, misc2;
        /** relative index in state array. Needed sometimes. */
        public int id;
		
        
        public String toString(){
            sb.setLength(0);
            sb.append(this.getClass().getName());
            sb.append(" sprite ");
            sb.append(this.sprite.name());
            sb.append(" frame ");
            sb.append(this.frame);

            return sb.toString();
            
        }
        
        protected static StringBuilder sb=new StringBuilder();

        /*@Override
        public void read(DoomFile f)
                throws IOException {
            this.sprite = spritenum_t.values()[f.readLEInt()];
            this.frame = f.readLEInt();
            this.tics = f.readLong();
            this.action = think_t.values()[f.readInt()];
            this.nextstate = statenum_t.values()[f.readInt()];
            this.misc1 = f.readInt();
            this.misc2 = f.readInt();
            
        } */
}

package data;
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: sounds.java,v 1.1 2010/06/30 08:58:51 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: sounds.java,v $
// Revision 1.1  2010/06/30 08:58:51  velktron
// Let's see if this stuff will finally commit....
//
//
// Most stuff is still  being worked on. For a good place to start and get an idea of what is being done, I suggest checking out the "testers" package.
//
// Revision 1.1  2010/06/29 11:07:34  velktron
// Release often, release early they say...
//
// Commiting ALL stuff done so far. A lot of stuff is still broken/incomplete, and there's still mixed C code in there. I suggest you load everything up in Eclpise and see what gives from there.
//
// A good place to start is the testers/ directory, where you  can get an idea of how a few of the implemented stuff works.
//
//
// DESCRIPTION:
//	Created by a sound utility.
//	Kept as a sample, DOOM2 sounds.
//
//-----------------------------------------------------------------------------

public class sounds{

//
// Information about all the music
//

public static musicinfo_t[] S_music= 
{
    new musicinfo_t(null),
    new musicinfo_t( "e1m1", 0 ),
    new musicinfo_t( "e1m2", 0 ),
    new musicinfo_t( "e1m3", 0 ),
    new musicinfo_t( "e1m4", 0 ),
    new musicinfo_t( "e1m5", 0 ),
    new musicinfo_t( "e1m6", 0 ),
    new musicinfo_t( "e1m7", 0 ),
    new musicinfo_t( "e1m8", 0 ),
    new musicinfo_t( "e1m9", 0 ),
    new musicinfo_t( "e2m1", 0 ),
    new musicinfo_t( "e2m2", 0 ),
    new musicinfo_t( "e2m3", 0 ),
    new musicinfo_t( "e2m4", 0 ),
    new musicinfo_t( "e2m5", 0 ),
    new musicinfo_t( "e2m6", 0 ),
    new musicinfo_t( "e2m7", 0 ),
    new musicinfo_t( "e2m8", 0 ),
    new musicinfo_t( "e2m9", 0 ),
    new musicinfo_t( "e3m1", 0 ),
    new musicinfo_t( "e3m2", 0 ),
    new musicinfo_t( "e3m3", 0 ),
    new musicinfo_t( "e3m4", 0 ),
    new musicinfo_t( "e3m5", 0 ),
    new musicinfo_t( "e3m6", 0 ),
    new musicinfo_t( "e3m7", 0 ),
    new musicinfo_t( "e3m8", 0 ),
    new musicinfo_t( "e3m9", 0 ),
    new musicinfo_t( "inter", 0 ),
    new musicinfo_t( "intro", 0 ),
    new musicinfo_t( "bunny", 0 ),
    new musicinfo_t( "victor", 0 ),
    new musicinfo_t( "introa", 0 ),
    new musicinfo_t( "runnin", 0 ),
    new musicinfo_t( "stalks", 0 ),
    new musicinfo_t( "countd", 0 ),
    new musicinfo_t( "betwee", 0 ),
    new musicinfo_t( "doom", 0 ),
    new musicinfo_t( "the_da", 0 ),
    new musicinfo_t( "shawn", 0 ),
    new musicinfo_t( "ddtblu", 0 ),
    new musicinfo_t( "in_cit", 0 ),
    new musicinfo_t( "dead", 0 ),
    new musicinfo_t( "stlks2", 0 ),
    new musicinfo_t( "theda2", 0 ),
    new musicinfo_t( "doom2", 0 ),
    new musicinfo_t( "ddtbl2", 0 ),
    new musicinfo_t( "runni2", 0 ),
    new musicinfo_t( "dead2", 0 ),
    new musicinfo_t( "stlks3", 0 ),
    new musicinfo_t( "romero", 0 ),
    new musicinfo_t( "shawn2", 0 ),
    new musicinfo_t( "messag", 0 ),
    new musicinfo_t( "count2", 0 ),
    new musicinfo_t( "ddtbl3", 0 ),
    new musicinfo_t( "ampie", 0 ),
    new musicinfo_t( "theda3", 0 ),
    new musicinfo_t( "adrian", 0 ),
    new musicinfo_t( "messg2", 0 ),
    new musicinfo_t( "romer2", 0 ),
    new musicinfo_t( "tense", 0 ),
    new musicinfo_t( "shawn3", 0 ),
    new musicinfo_t( "openin", 0 ),
    new musicinfo_t( "evil", 0 ),
    new musicinfo_t( "ultima", 0 ),
    new musicinfo_t( "read_m", 0 ),
    new musicinfo_t( "dm2ttl", 0 ),
    new musicinfo_t( "dm2int", 0 ) 
};


//
// Information about all the sfx
//

public static sfxinfo_t nullSfxLink;

public static sfxinfo_t[] S_sfx =
{
  // S_sfx[0] needs to be a dummy for odd reasons.
  new sfxinfo_t( "none", false,  0, -1, -1, 0 ),

  new sfxinfo_t( "pistol", false, 64, -1, -1, 0 ),
  new sfxinfo_t( "shotgn", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "sgcock", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "dshtgn", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "dbopn", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "dbcls", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "dbload", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "plasma", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "bfg", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "sawup", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "sawidl", false, 118,  -1, -1, 0 ),
  new sfxinfo_t( "sawful", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "sawhit", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "rlaunc", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "rxplod", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "firsht", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "firxpl", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "pstart", false, 100,  -1, -1, 0 ),
  new sfxinfo_t( "pstop", false, 100,  -1, -1, 0 ),
  new sfxinfo_t( "doropn", false, 100,  -1, -1, 0 ),
  new sfxinfo_t( "dorcls", false, 100,  -1, -1, 0 ),
  new sfxinfo_t( "stnmov", false, 119,  -1, -1, 0 ),
  new sfxinfo_t( "swtchn", false, 78,  -1, -1, 0 ),
  new sfxinfo_t( "swtchx", false, 78,  -1, -1, 0 ),
  new sfxinfo_t( "plpain", false, 96,  -1, -1, 0 ),
  new sfxinfo_t( "dmpain", false, 96,  -1, -1, 0 ),
  new sfxinfo_t( "popain", false, 96,  -1, -1, 0 ),
  new sfxinfo_t( "vipain", false, 96,  -1, -1, 0 ),
  new sfxinfo_t( "mnpain", false, 96,  -1, -1, 0 ),
  new sfxinfo_t( "pepain", false, 96,  -1, -1, 0 ),
  new sfxinfo_t( "slop", false, 78,  -1, -1, 0 ),
  new sfxinfo_t( "itemup", true, 78,  -1, -1, 0 ),
  new sfxinfo_t( "wpnup", true, 78,  -1, -1, 0 ),
  new sfxinfo_t( "oof", false, 96,  -1, -1, 0 ),
  new sfxinfo_t( "telept", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "posit1", true, 98,  -1, -1, 0 ),
  new sfxinfo_t( "posit2", true, 98,  -1, -1, 0 ),
  new sfxinfo_t( "posit3", true, 98,  -1, -1, 0 ),
  new sfxinfo_t( "bgsit1", true, 98,  -1, -1, 0 ),
  new sfxinfo_t( "bgsit2", true, 98,  -1, -1, 0 ),
  new sfxinfo_t( "sgtsit", true, 98,  -1, -1, 0 ),
  new sfxinfo_t( "cacsit", true, 98,  -1, -1, 0 ),
  new sfxinfo_t( "brssit", true, 94,  -1, -1, 0 ),
  new sfxinfo_t( "cybsit", true, 92,  -1, -1, 0 ),
  new sfxinfo_t( "spisit", true, 90,  -1, -1, 0 ),
  new sfxinfo_t( "bspsit", true, 90,  -1, -1, 0 ),
  new sfxinfo_t( "kntsit", true, 90,  -1, -1, 0 ),
  new sfxinfo_t( "vilsit", true, 90,  -1, -1, 0 ),
  new sfxinfo_t( "mansit", true, 90,  -1, -1, 0 ),
  new sfxinfo_t( "pesit", true, 90,  -1, -1, 0 ),
  new sfxinfo_t( "sklatk", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "sgtatk", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "skepch", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "vilatk", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "claw", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "skeswg", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "pldeth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "pdiehi", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "podth1", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "podth2", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "podth3", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "bgdth1", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "bgdth2", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "sgtdth", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "cacdth", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "skldth", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "brsdth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "cybdth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "spidth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "bspdth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "vildth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "kntdth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "pedth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "skedth", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "posact", true, 120,  -1, -1, 0 ),
  new sfxinfo_t( "bgact", true, 120,  -1, -1, 0 ),
  new sfxinfo_t( "dmact", true, 120,  -1, -1, 0 ),
  new sfxinfo_t( "bspact", true, 100,  -1, -1, 0 ),
  new sfxinfo_t( "bspwlk", true, 100,  -1, -1, 0 ),
  new sfxinfo_t( "vilact", true, 100,  -1, -1, 0 ),
  new sfxinfo_t( "noway", false, 78,  -1, -1, 0 ),
  new sfxinfo_t( "barexp", false, 60,  -1, -1, 0 ),
  new sfxinfo_t( "punch", false, 64,  -1, -1, 0 ),
  new sfxinfo_t( "hoof", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "metal", false, 70,  -1, -1, 0 ),
  // MAES: here C referenced a field before it was defined. 
  // We'll make do by defining a new "linked" boolean field, and
  // handling special cases in a separate initializer.
  new sfxinfo_t( "chgun", false, 64, true, 150, 0, 0 ),
  new sfxinfo_t( "tink", false, 60,  -1, -1, 0 ),
  new sfxinfo_t( "bdopn", false, 100,  -1, -1, 0 ),
  new sfxinfo_t( "bdcls", false, 100,  -1, -1, 0 ),
  new sfxinfo_t( "itmbk", false, 100,  -1, -1, 0 ),
  new sfxinfo_t( "flame", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "flamst", false, 32,  -1, -1, 0 ),
  new sfxinfo_t( "getpow", false, 60,  -1, -1, 0 ),
  new sfxinfo_t( "bospit", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "boscub", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "bossit", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "bospn", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "bosdth", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "manatk", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "mandth", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "sssit", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "ssdth", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "keenpn", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "keendt", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "skeact", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "skesit", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "skeatk", false, 70,  -1, -1, 0 ),
  new sfxinfo_t( "radio", false, 60, -1, -1, 0 )
};

/** MAES: This method is here to handle exceptions in definitions of static sfx.
 *  Only the chaingun sound needs to be cross-linked to the pistol sound, but in 
 *  Java you can't do that until the array is actually created. So remember to run
 *  this explicitly, and add any further rules you want!
 *  
 */

public static void init(){
    for (int i=0;i<S_sfx.length;i++){
        if (S_sfx[i].linked){
            // MAES: Rule for chgun
            if (S_sfx[i].name.compareToIgnoreCase("chgun")==0) {
                S_sfx[i].link=S_sfx[sfxenum_t.sfx_pistol.ordinal()];
            }
        }
    }
    
}

public static enum  musicenum_t
{
    mus_None,
    mus_e1m1,
    mus_e1m2,
    mus_e1m3,
    mus_e1m4,
    mus_e1m5,
    mus_e1m6,
    mus_e1m7,
    mus_e1m8,
    mus_e1m9,
    mus_e2m1,
    mus_e2m2,
    mus_e2m3,
    mus_e2m4,
    mus_e2m5,
    mus_e2m6,
    mus_e2m7,
    mus_e2m8,
    mus_e2m9,
    mus_e3m1,
    mus_e3m2,
    mus_e3m3,
    mus_e3m4,
    mus_e3m5,
    mus_e3m6,
    mus_e3m7,
    mus_e3m8,
    mus_e3m9,
    mus_inter,
    mus_intro,
    mus_bunny,
    mus_victor,
    mus_introa,
    mus_runnin,
    mus_stalks,
    mus_countd,
    mus_betwee,
    mus_doom,
    mus_the_da,
    mus_shawn,
    mus_ddtblu,
    mus_in_cit,
    mus_dead,
    mus_stlks2,
    mus_theda2,
    mus_doom2,
    mus_ddtbl2,
    mus_runni2,
    mus_dead2,
    mus_stlks3,
    mus_romero,
    mus_shawn2,
    mus_messag,
    mus_count2,
    mus_ddtbl3,
    mus_ampie,
    mus_theda3,
    mus_adrian,
    mus_messg2,
    mus_romer2,
    mus_tense,
    mus_shawn3,
    mus_openin,
    mus_evil,
    mus_ultima,
    mus_read_m,
    mus_dm2ttl,
    mus_dm2int,
    NUMMUSIC
};

public static enum  sfxenum_t
{
    sfx_None,
    sfx_pistol,
    sfx_shotgn,
    sfx_sgcock,
    sfx_dshtgn,
    sfx_dbopn,
    sfx_dbcls,
    sfx_dbload,
    sfx_plasma,
    sfx_bfg,
    sfx_sawup,
    sfx_sawidl,
    sfx_sawful,
    sfx_sawhit,
    sfx_rlaunc,
    sfx_rxplod,
    sfx_firsht,
    sfx_firxpl,
    sfx_pstart,
    sfx_pstop,
    sfx_doropn,
    sfx_dorcls,
    sfx_stnmov,
    sfx_swtchn,
    sfx_swtchx,
    sfx_plpain,
    sfx_dmpain,
    sfx_popain,
    sfx_vipain,
    sfx_mnpain,
    sfx_pepain,
    sfx_slop,
    sfx_itemup,
    sfx_wpnup,
    sfx_oof,
    sfx_telept,
    sfx_posit1,
    sfx_posit2,
    sfx_posit3,
    sfx_bgsit1,
    sfx_bgsit2,
    sfx_sgtsit,
    sfx_cacsit,
    sfx_brssit,
    sfx_cybsit,
    sfx_spisit,
    sfx_bspsit,
    sfx_kntsit,
    sfx_vilsit,
    sfx_mansit,
    sfx_pesit,
    sfx_sklatk,
    sfx_sgtatk,
    sfx_skepch,
    sfx_vilatk,
    sfx_claw,
    sfx_skeswg,
    sfx_pldeth,
    sfx_pdiehi,
    sfx_podth1,
    sfx_podth2,
    sfx_podth3,
    sfx_bgdth1,
    sfx_bgdth2,
    sfx_sgtdth,
    sfx_cacdth,
    sfx_skldth,
    sfx_brsdth,
    sfx_cybdth,
    sfx_spidth,
    sfx_bspdth,
    sfx_vildth,
    sfx_kntdth,
    sfx_pedth,
    sfx_skedth,
    sfx_posact,
    sfx_bgact,
    sfx_dmact,
    sfx_bspact,
    sfx_bspwlk,
    sfx_vilact,
    sfx_noway,
    sfx_barexp,
    sfx_punch,
    sfx_hoof,
    sfx_metal,
    sfx_chgun,
    sfx_tink,
    sfx_bdopn,
    sfx_bdcls,
    sfx_itmbk,
    sfx_flame,
    sfx_flamst,
    sfx_getpow,
    sfx_bospit,
    sfx_boscub,
    sfx_bossit,
    sfx_bospn,
    sfx_bosdth,
    sfx_manatk,
    sfx_mandth,
    sfx_sssit,
    sfx_ssdth,
    sfx_keenpn,
    sfx_keendt,
    sfx_skeact,
    sfx_skesit,
    sfx_skeatk,
    sfx_radio,
    NUMSFX
};



}


package data;

import static data.Tables.FINEANGLES;
import static data.Tables.SLOPERANGE;
import static data.Tables.tantoangle;
import static m.fixed_t.*;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: Tables.java,v 1.22 2011/05/06 09:21:59 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: Tables.java,v $
// Revision 1.22  2011/05/06 09:21:59  velktron
// Cleaned up and reorganized common renderer code.
//
// Revision 1.21  2011/02/11 00:11:13  velktron
// A MUCH needed update to v1.3.
//
// Revision 1.20  2010/12/20 17:15:08  velktron
// Made the renderer more OO -> TextureManager and other changes as well.
//
// Revision 1.19  2010/12/10 17:38:56  velktron
// pspritescale fixed, weapon actions won't crash (but not work either).
//
// Revision 1.18  2010/11/25 20:12:44  velktron
// Fixed blockmap bug and viewangletox overflow bug.
//
// Revision 1.17  2010/11/22 01:17:16  velktron
// Fixed blockmap (for the most part), some actions implemented and functional, ambient animation/lighting functional.
//
// Revision 1.16  2010/11/17 23:55:06  velktron
// Kind of playable/controllable.
//
// Revision 1.15  2010/11/15 17:15:54  velktron
// Fixed masked columns rendering, introduced unrolled span and column functions from Boom (thanks, Lee Killough :-)
//
// Revision 1.14  2010/11/14 20:00:21  velktron
// Bleeding floor bug fixed!
//
// Revision 1.13  2010/11/12 13:37:25  velktron
// Rationalized the LUT system - now it's 100% procedurally generated.
//
// Revision 1.12  2010/11/03 16:48:04  velktron
// "Bling" view angles fixed (perhaps related to the "bleeding line bug"?)
//
// Revision 1.11  2010/10/14 18:37:14  velktron
// Rendering kinda works. Wow.
//
// Revision 1.10  2010/10/08 16:55:50  velktron
// Duh
//
// Revision 1.9  2010/10/01 16:47:51  velktron
// Fixed tab interception.
//
// Revision 1.8  2010/09/27 15:07:44  velktron
// meh
//
// Revision 1.7  2010/09/27 02:27:29  velktron
// BEASTLY update
//
// Revision 1.6  2010/09/22 16:40:02  velktron
// MASSIVE changes in the status passing model.
// DoomMain and DoomGame unified.
// Doomstat merged into DoomMain (now status and game functions are one).
//
// Most of DoomMain implemented. Possible to attempt a "classic type" start but will stop when reading sprites.
//
// Revision 1.5  2010/09/21 15:53:37  velktron
// Split the Map ...somewhat...
//
// Revision 1.4  2010/09/16 00:16:27  velktron
// Velvet FM 96.8
//
// Revision 1.3  2010/09/15 16:17:38  velktron
// Arithmetic
//
// Revision 1.2  2010/09/09 16:09:09  velktron
// Yer more enhancements to the display system...
//
// Revision 1.1  2010/07/05 16:18:40  velktron
// YOU DON'T WANNA KNOW
//
// Revision 1.1  2010/06/30 08:58:51  velktron
// Let's see if this stuff will finally commit....
//
//
// Most stuff is still  being worked on. For a good place to start and get an idea of what is being done, I suggest checking out the "testers" package.
//
// Revision 1.1  2010/06/29 11:07:34  velktron
// Release often, release early they say...
//
// Commiting ALL stuff done so far. A lot of stuff is still broken/incomplete, and there's still mixed C code in there. I suggest you load everything up in Eclpise and see what gives from there.
//
// A good place to start is the testers/ directory, where you  can get an idea of how a few of the implemented stuff works.
//
//
// DESCRIPTION:
//	Lookup tables.
//	Do not try to look them up :-).
//	In the order of appearance: 
//
//	int finetangent[4096]	- Tangens LUT.
//	 Should work with BAM fairly well (12 of 16bit,
//      effectively, by shifting).
//
//	int finesine[10240]		- Sine lookup.
//	 Guess what, serves as cosine, too.
//	 Remarkable thing is, how to use BAMs with this?
//
//	int tantoangle[2049]	- ArcTan LUT,
//	  maps tan(angle) to angle fast. Gotta search.
//	
//    
//-----------------------------------------------------------------------------

public final class Tables {

    public static final String rcsid="$Id:";

   public static final double PI =             3.141592657;

   /** Normally set to 12, and this sets the value of other constants too.
    *  Howevever changing it will also distort the view, resulting in a 
    *  nightmare-like vision. There are some practical minimum and 
    *  maximums as well.
    *  
    * 
    */
   
  public static final int BITSPRECISION = 12;
  public static final int FINEANGLES  =    2<<BITSPRECISION;
  public static final int FINETANS = FINEANGLES/2; // 4096 for normal precision.
  public static final int QUARTERMARK = 2<<BITSPRECISION-2;
  public static final int FINEMASK =       (FINEANGLES-1);
  /** Mod long angle_t's with this value to cut off rollover */
  public static final long ANGLEMODULE = 0x100000000L;
  
  /** AND with this to remove unwanted sign extensions */
  public static final long BITS32 = 0x00000000FFFFFFFFL;
  
  /** Sign elimination */
  public static final int BITS31 = 0x7FFFFFFF;

  
  // Maes: we have to procedurally generate finesine/finecosine, else we run into a Java static limit.
  // Either that, or I split the files. Guess what I did.
 // public static int PRECISION = 10240 ;

  /** 0x100000000 to 0x2000 */
  public static final int ANGLETOFINESHIFT =   31-BITSPRECISION;
    
/* Binary Angle Measurement.
 * Some maths: their definition means that a range of 2pi is actually
 * mapped to 2^32 values!!! But the lookup tables are only 8K (2^13)
 * long (for sine/cosine), which means that we're 19 bits too precise
 * -> ergo, >>ANGLETOFINESHIFT must be applied.
 * 
 * Also, the original angle_t type was "unsigned int", so we should be
 * using longs here. However, as BAM is used only after shifting, so 
 * using ints doesn't cause a problem for LUT access.
 *  
 * However, some problems may arise with comparisons and ordinary arithmetic: 
 * e.g. ANG270 is supposed to be larger not only than ANG180, but also from 
 * ANG45, which does not hold true if those constants were stored as ints.
 * 
 * As a rule of thumb, whenever you need to store JUST a BAM index, then 
 * ints are ok (actually, you'll have to cast down to int anyway).
 * 
 * Whenever you need to add or compare angles directly however, you need 
 * longs. Furthermore, you must account for possible rollovers by modding
 * with 0x100000000 or else long ints will store angles exceeding 360 degrees!
 * Under no circumstances the value actually stored in the "long angles" should
 * exceed 0xFFFFFFFF.
 * 
 * An example: comparing any two long angles directly is OK, provided they were
 * constructed correctly.
 * 
 * Adding, subtracting, multiplying etc. with two or more angles however requires
 * rollover compensation (e.g. result=(a+b+c) is wrong, result=(a+b+c)%0xFFFFFFFF
 * is correct and will produce an angle you can "trust".
 * 
 * 
 */
  
  /** Doom angle constants. */
  
public static final long ANG45 =  0x20000000L,
                        ANG90  =     0x40000000L,
                        ANG180 =     0x80000000L,
                        ANG270 =     0xc0000000L;

public static final int SLOPERANGE =    (2<<(BITSPRECISION-2)); // Normally 2048.
public static final int SLOPEBITS  =     BITSPRECISION-1;
public static final int DBITS=FRACBITS-SLOPEBITS;

//  typedef unsigned angle_t;


  // Effective size is 2049;
  // The +1 size is to handle the case when x==y
  //  without additional checking.
  //extern angle_t      tantoangle[SLOPERANGE+1];

/**
 * Original size was 10240, but includes 5PI/4 periods. We can get away with
 * ints on this one because of the small range. MAES: WTF? -64 ~ 64K
 * range... so 17-bit accuracy? heh.
 */

public static final int[] finesine=new int[FINEANGLES+QUARTERMARK];
public static final int[] finecosine=new int[FINEANGLES];

/** Any denominator smaller than 512 will result in 
 *  maximum slope (45 degrees, or an index into tantoangle of 2048)
 *  The original method used unsigned args. So if this returns NEGATIVES
 *  in any way, it means you fucked up. Another "consistency" for Doom.
 *  Even though it was called upon fixed_t signed numbers.
 * 
 */
public static final int SlopeDiv ( long	num, long den)
{
    int 	ans;
    
    if (den < 512)
	return SLOPERANGE;

    ans = (int) ((num<<3)/(den>>>8));

    return ans <= SLOPERANGE ? ans : SLOPERANGE;
}

/** Finetangent table. It only has 4096 values corresponding roughly
 * to -90/+90 angles, with values between are -/+ 2607 for "infinity".
 * 
 * Since in vanilla accesses to the table can overflow way beyond 4096
 * indexes, the access index must be clipped to 4K tops via an accessor,
 * or, in order to simulate some aspects of vanilla overflowing, replicate
 * 4K of finesine's values AFTER the 4K index. This removes the need
 * for access checking, at the cost of some extra memory. It also allows
 * a small degree of "vanilla like" compatibility.
 * 
 * 
 */

public final static int[] finetangent=new int[2*FINETANS];


// MAES: original range 2049
// This obviously 
// Range goes from 0x00000000 to 0x20000000, so in theory plain ints should be enough...

/** This maps a value 0-2048 to a BAM unsigned integer angle, ranging from 0x0 to 0x2000000:
 * 
 * In practice, this means there are only tangent values for angles up to 45 degrees. 
 *  
 * These values are valid BAM measurements in the first quadrant
 * 
 * 
 */

public static final int[] tantoangle=new int[SLOPERANGE+1];

/** Use this to get a value from the finesine table. It will be automatically shifte, 
 *  Equivalent to finesine[angle>>>ANGLETOFINESHIFT]
 * 
 * @param angle in BAM units
 * @return
 */
public static final int finesine(int angle){
    return finesine[angle>>>ANGLETOFINESHIFT];
}

/** Use this to get a value from the finesine table using a long argument.
 * It will automatically shift, apply rollover module and cast.
 * 
 * Equivalent to finesine[(int) ((angle>>ANGLETOFINESHIFT)%ANGLEMODULE)];
 * 
 * @param angle in BAM units
 * @return
 */
public static final int finesine(long angle){
    return finesine[(int) ((angle&BITS32)>>>ANGLETOFINESHIFT)];
}

/** Use this to get a value from the finecosine table. It will be automatically shifted, 
 * Equivalent to finecosine[angle>>>ANGLETOFINESHIFT]
 * @param angle in BAM units
 * @return
 */
public static final int finecosine(int angle){
    return finecosine[angle>>>ANGLETOFINESHIFT];
}

/** Use this to get a value from the finecosine table. 
 * It will automatically shift, apply rollover module and cast.
 *  
 * Equivalent to finecosine[(int) ((angle&BITS32)>>>ANGLETOFINESHIFT)]
 * @param angle in BAM units
 * @return
 */
public static final int finecosine(long angle){
    return finecosine[(int) ((angle&BITS32)>>>ANGLETOFINESHIFT)];
}

/** Compare BAM angles in 32-bit format 
 *  "Greater or Equal" bam0>bam1
 * */

public static final boolean GE(int bam0, int bam1){
    // Handle easy case.
    if (bam0==bam1) return true;
    
    // bam0 is greater than 180 degrees.
    if (bam0<0 && bam1>=0) return true;
    // bam1 is greater than 180 degrees.
    if (bam0>=0 && bam1<0) return false;
    
    // Both "greater than 180", No other way to compare.
    bam0&=BITS31;
    bam1&=BITS31;        
    return bam0>bam1;
}

public static final boolean GT(int bam0, int bam1){       
    // bam0 is greater than 180 degrees.
    if (bam0<0 && bam1>=0) return true;
    // bam1 is greater than 180 degrees.
    if (bam0>=0 && bam1<0) return false;
    
    // Both "greater than 180", No other way to compare.
    bam0&=BITS31;
    bam1&=BITS31;        
    return bam0>bam1;
}

public static final int BAMDiv(int bam0, int bam1){       
    // bam0 is greater than 180 degrees.
    if (bam0>=0) return bam0/bam1;
    // bam0 is greater than 180 degrees.
    // We have to make is so that ANG270 0xC0000000 becomes ANG135, aka 60000000
    if (bam1>=0)
    return (int) ((long)(0x0FFFFFFFFL&bam0)/bam1);
    
    return (int) ((long)(0x0FFFFFFFFL&bam0)/(0x0FFFFFFFFL&bam1));
}

/** Converts a long angle to a BAM LUT-ready angle (13 bits, between 0-8191). 
 *  Cuts away rollover. 
 *  
 * @param angle
 * @return
 */

public static final int toBAMIndex(long angle){
    return (int) ((angle&BITS32)>>>ANGLETOFINESHIFT);
}

/** Converts a long angle to a TAN BAM  LUT-ready angle (12 bits, between 0-4195). 
 *  Cuts away rollover. 
 *  
 * @param angle
 * @return
 */

public static final int toFineTanIndex(long angle){
    return (int) ((angle&BITS31)>>>ANGLETOFINESHIFT);
}

/** Converts an 32-bit int angle to a BAM LUT-ready angle (13 bits, between 0-8192). 
 * 
 * @param angle
 * @return
 */

public static final int toBAMIndex(int angle){
    return angle>>>ANGLETOFINESHIFT;
}

/** Add two long angles and correct for overflow */

public static final long addAngles(long a, long b) {
    return ((a+b)&BITS32);
}

/** MAES: I brought this function "back from the dead" since
 *  Java has some pretty low static limits for statically defined LUTs.
 *  In order to keep the codebase clutter and static allocation to a minimum,
 *  I decided to procedurally generate the tables during runtime, 
 *  using the original functions.
 *    
 *  The code has been thoroughly checked in both Sun's JDK and GCC and was
 *  found to, indeed, produce the same values found in the finesine/finecosine
 *  and finetangent tables, at least on Intel.
 *  
 *  The "tantoangle" table is also generated procedurally, but since there 
 *  was no "dead code" to build upon, it was recreated through reverse
 *  engineering and also found to be 100% faithful to the original data.  
 * 
 * 
 */

public static void InitTables(){
    int     i;
    float   a;
    float   fv;
    int     t;
    
    // viewangle tangent table
    for (i=0 ; i<FINEANGLES/2 ; i++)
    {
    a = (float)((i-FINEANGLES/4+0.5)*PI*2)/FINEANGLES;
    fv = (float)(FRACUNIT*Math.tan (a));
    t = (int)fv;
    finetangent[i] = t;
    } 
    
    // finesine table
    for (i=0 ; i<FINEANGLES+QUARTERMARK ; i++)
    {
    // OPTIMIZE: mirror...
    a = (float)((i+0.5)*PI*2)/FINEANGLES;
    t = (int)(FRACUNIT*Math.sin (a));
    finesine[i] = t;
    if (i>=QUARTERMARK){
        finecosine[i-QUARTERMARK] = t;
        }
    }
    
    // HACK: replicate part of finesine after finetangent, to
    // simulate overflow behavior and remove need for capping
    // indexes
    // viewangle tangent table
    for (i=FINEANGLES/2 ; i<FINEANGLES ; i++)
    {
    finetangent[i] = finesine[i-FINEANGLES/2];
    } 
    
    /* tantoangle table
     * There was actually no dead code for that one, so this is a close recreation.
     * Since there are 2049 values, and the maximum angle considered is 536870912 (0x20000000)
     * which is 45 degrees in BAM, we have to fill in the atan for values up to 45 degrees.
     * Since the argument is a slope ranging from 0...2048, we have 2049 equally spaced (?)
     *  values, with 2048 being being the unitary slope (0x10000 in fixed_t). That value is only
     *  accessed in special cases (overflow) so we only need to consider 0..2047 aka 11 bits.
     *  So: we take "minislopes" 0-2048, we blow them up to a full fixed_t unit with <<5.
     *  We make this into a float (?), then use trigonometric ATAN, and then go to BAM.
     *  
     *  Any questions?
     *  
     */    
    
    /* This is the recreated code 
    for (i=0 ; i<SLOPERANGE+1 ; i++)
    {
    
    a=(float)((i<<DBITS)/65536.0);
    t=(int)((float)(2*Math.atan(a)/PI)*0x40000000); 
    tantoangle[i] = t;
    } 
    */
    
    // This is the original R_InitPointToAngle code that created this table.
    for (i=0 ; i<=SLOPERANGE ; i++)
    {
 a = (float) (Math.atan( (double)i/SLOPERANGE )/(3.141592657*2));
 t = (int) (0xffffffffL*a);
 tantoangle[i] = (int) t;
    }
    
    }

private Tables(){
    
}

}


package data;

import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import w.CacheableDoomObject;
import w.DoomBuffer;
import w.IPackableDoomObject;
import w.IWritableDoomObject;

/**
 * A SideDef, defining the visual appearance of a wall, by setting textures and
 * offsets. ON-DISK.
 */

public class mapsidedef_t implements CacheableDoomObject,IWritableDoomObject,IPackableDoomObject{

    public mapsidedef_t() {

    }

    public short textureoffset;

    public short rowoffset;

    // 8-char strings.
    public String toptexture;

    public String bottomtexture;

    public String midtexture;

    /** Front sector, towards viewer. */
    public short sector;

    public static int sizeOf() {
        return 30;
    }

    @Override
    public void unpack(ByteBuffer buf)
            throws IOException {
        buf.order(ByteOrder.LITTLE_ENDIAN);
        this.textureoffset = buf.getShort();
        this.rowoffset = buf.getShort();
        this.toptexture=DoomBuffer.getNullTerminatedString(buf,8).toUpperCase();
        this.bottomtexture=DoomBuffer.getNullTerminatedString(buf,8).toUpperCase();
        this.midtexture=DoomBuffer.getNullTerminatedString(buf,8).toUpperCase();
        this.sector = buf.getShort();
        
    }

	@Override
	public void pack(ByteBuffer buf) throws IOException {
	    buf.order(ByteOrder.LITTLE_ENDIAN);
	    buf.putShort(textureoffset);
	    buf.putShort(rowoffset);
	    DoomBuffer.putNullTerminatedString(buf,toptexture,8);
	    DoomBuffer.putNullTerminatedString(buf,bottomtexture,8);
	    DoomBuffer.putNullTerminatedString(buf,midtexture,8);
	    buf.putShort(sector);		
	}

	@Override
	public void write(DataOutputStream dos) throws IOException {
        // More efficient, avoids duplicating code and
        // handles little endian better.
        iobuffer.position(0);
        iobuffer.order(ByteOrder.LITTLE_ENDIAN);
        this.pack(iobuffer);
        dos.write(iobuffer.array());				
	}
	
	private static ByteBuffer iobuffer=ByteBuffer.allocate(mapsidedef_t.sizeOf());
}

package i;

import doom.ticcmd_t;

public interface IDoomSystem {

	public void AllocLow(int length);

	public void BeginRead();

	public void EndRead();

	public void WaitVBL(int count);

	public byte[] ZoneBase(int size);

	public int GetHeapSize();

	public void Tactile(int on, int off, int total);

	public void Quit();

	public ticcmd_t BaseTiccmd();

	public void Error(String error, Object ... args);

	void Error(String error);
	
	void Init();
	
	/** Generate a blocking alert with the intention of continuing or aborting
	 * a certain game-altering action. E.g. loading PWADs, or upon critical 
	 * level loading failures. This can be either a popup panel or console 
	 * message.
	 *  
	 * @param cause Provide a clear string explaining why the alert was generated
	 * @return true if we should continue, false if an alternate action should be taken.
	 */
	boolean GenerateAlert(String title,String cause);


}

package i;

import doom.DoomStatus;
import rr.patch_t;
import v.DoomVideoRenderer;
import v.IVideoScale;
import w.IWadLoader;

public class DiskDrawer implements IDiskDrawer,DoomStatusAware {

	private patch_t disk;
	private IWadLoader W;
	private DoomVideoRenderer<?,?> V;
	private IVideoScale VS;
	private int timer=0;
	private String diskname;
	
	public static final String STDISK="STDISK";
	public static final String STCDROM="STCDROM";
	
	public DiskDrawer(DoomStatus<?,?> DM,String icon){		
		this.updateStatus(DM);
		this.diskname=icon;
	}

	@Override
	public void Init(){
		this.disk=W.CachePatchName(diskname);
	}
	
	@Override
	public void Drawer() {
		if (timer>0){
			if (timer%2==0)
		V.DrawScaledPatch(304,184,DoomVideoRenderer.SCREEN_FG,VS, disk);
		}
		if (timer>=0)
			timer--;
	}

	@Override
	public void updateStatus(DoomStatus<?,?> DC) {
		this.W=DC.W;
		this.V=DC.V;		
	    }

	@Override
	public void setVideoScale(IVideoScale vs) {
		this.VS = vs;
	}

	@Override
	public void initScaling() {

	}

	@Override
	public void setReading(int reading) {
		timer=reading;
	}

	@Override
	public boolean isReading() {
		return timer>0;
	}

	@Override
	public boolean justDoneReading() {
		return timer==0;
	}
	
}

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: system.java,v 1.5 2011/02/11 00:11:13 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: system.java,v $
// Revision 1.5  2011/02/11 00:11:13  velktron
// A MUCH needed update to v1.3.
//
// Revision 1.1  2010/06/30 08:58:50  velktron
// Let's see if this stuff will finally commit....
//
//
// Most stuff is still  being worked on. For a good place to start and get an idea of what is being done, I suggest checking out the "testers" package.
//
// Revision 1.1  2010/06/29 11:07:34  velktron
// Release often, release early they say...
//
// Commiting ALL stuff done so far. A lot of stuff is still broken/incomplete, and there's still mixed C code in there. I suggest you load everything up in Eclpise and see what gives from there.
//
// A good place to start is the testers/ directory, where you  can get an idea of how a few of the implemented stuff works.
//
//
// DESCRIPTION:
//
//-----------------------------------------------------------------------------

package i;

public class system{
    
/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <stdarg.h>
#include <sys/time.h>
#include <unistd.h>

#include "doomdef.h"
#include "m_misc.h"
#include "i_video.h"
#include "i_sound.h"

#include "d_net.h"
#include "g_game.h"

#ifdef __GNUG__
#pragma implementation "i_system.h"
#endif
#include "i_system.h"

*/


static int	mb_used = 6;


public void
Tactile
( int	on,
  int	off,
  int	total )
{
  // UNUSED.
  on = off = total = 0;
}

/*
ticcmd_t	emptycmd;
ticcmd_t*	I_BaseTiccmd(void)
{
    return &emptycmd;
}

*/

public static int  GetHeapSize ()
{
    return mb_used*1024*1024;
}

/*
byte* I_ZoneBase (int*	size)
{
    *size = mb_used*1024*1024;
    return (byte *) malloc (*size);
}
*/


//
// I_GetTime
// returns time in 1/70th second tics
//
/*
int  I_GetTime ()
{
    struct timeval	tp;
    struct timezone	tzp;
    int			newtics;
    static int		basetime=0;
  
    gettimeofday(&tp, &tzp);
    if (!basetime)
	basetime = tp.tv_sec;
    newtics = (tp.tv_sec-basetime)*TICRATE + tp.tv_usec*TICRATE/1000000;
    return newtics;
}
*/


//
// I_Init
//
/*
void I_Init (void)
{
    I_InitSound();
    //  I_InitGraphics();
}

//
// I_Quit
//
void I_Quit (void)
{
    D_QuitNetGame ();
    I_ShutdownSound();
    I_ShutdownMusic();
    M_SaveDefaults ();
    I_ShutdownGraphics();
    exit(0);
}

void I_WaitVBL(int count)
{
#ifdef SGI
    sginap(1);                                           
#else
#ifdef SUN
    sleep(0);
#else
    usleep (count * (1000000/70) );                                
#endif
#endif
}

void I_BeginRead(void)
{
}

void I_EndRead(void)
{
}

byte*	I_AllocLow(int length)
{
    byte*	mem;
        
    mem = (byte *)malloc (length);
    memset (mem,0,length);
    return mem;
}

*/

//
// I_Error
//
public static boolean demorecording;

public static void Error (String error, Object ... args)
{
    //va_list	argptr;

    // Message first.
    //va_start (argptr,error);
    System.err.print("Error: ");
    System.err.printf(error,args);
    System.err.print("\n");
    //va_end (argptr);

    //fflush( stderr );

    // Shutdown. Here might be other errors.
    //if (demorecording)
	//G_CheckDemoStatus();

    //D_QuitNetGame ();
    //I_ShutdownGraphics();
    
    System.exit(-1);
}
}

package i;

/** Interface for Doom-to-System event handling methods
 * 
 * @author Velktron
 *
 */


public interface DoomEventInterface {

	/** The implementation is windowing subsystem-specific 
	 *  e.g. DOS, XServer, AWT or Swing or whatever.
	 * 
	 */
	public void GetEvent();


}

package i;

import v.IVideoScaleAware;

public interface IDiskDrawer extends IDrawer,IVideoScaleAware{
	
	/** Set a timeout (in tics) for displaying the disk icon 
	 * 
	 * @param timeout
	 */
	
	void setReading(int reading);
	
	/** Disk displayer is currently active
	 * 
	 * @return
	 */
	boolean isReading();
	
	/** Only call after the Wadloader is instantiated and
	 *  initialized itself.
	 * 
	 */
	void Init();
	
	/**Status only valid after the last tic has been drawn.
	 * Use to know when to redraw status bar.
	 * 
	 * @return
	 */
	boolean justDoneReading();
    	
}

package i;

public final class Strings {
	public static final String MOCHA_DOOM_TITLE="Mocha Doom Alpha 1.6";	
	
	public static final String MODIFIED_GAME=
		("===========================================================================\n"+
		 "ATTENTION:  This version of DOOM has been modified.  If you would like to\n"+
         "get a copy of the original game, call 1-800-IDGAMES or see the readme file.\n"+
         "        You will not receive technical support for modified games.\n"+
         "                      press enter to continue\n"+
         "===========================================================================\n");
	
	public static final String MODIFIED_GAME_TITLE="Modified game alert";
	
	public static final String MODIFIED_GAME_DIALOG=
		
		("<html><center>"+
		"===========================================================================<br>"+
		 "ATTENTION:  This version of DOOM has been modified.  If you would like to<br>"+
         "get a copy of the original game, call 1-800-IDGAMES or see the readme file.<br>"+
         "        You will not receive technical support for modified games.<br>"+
         "                      press OK to continue<br>"+
         "===========================================================================<br>"+
         "</center></html>");
	
	public static final String LEVEL_FAILURE_TITLE="Level loading failure";
	
	public static final String LEVEL_FAILURE_CAUSE=
		
		("<html><center>"+
		"Level loading failed!<br>"+
		 "Press OK to end this game without exiting, or cancel to quit Doom."+
         "</center></html>");
	
}

package i;

import doom.ticcmd_t;

public class DummySystem implements IDoomSystem{

    @Override
    public void AllocLow(int length) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void BeginRead() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void EndRead() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void WaitVBL(int count) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public byte[] ZoneBase(int size) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int GetHeapSize() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void Tactile(int on, int off, int total) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void Quit() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public ticcmd_t BaseTiccmd() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void Error(String error, Object... args) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void Error(String error) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void Init() {
        // TODO Auto-generated method stub
        
    }

    @Override
    public boolean GenerateAlert(String title, String cause) {
        // TODO Auto-generated method stub
        return false;
    }

}

package i;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: DoomSoundInterface.java,v 1.3 2011/02/11 00:11:13 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
//
// DESCRIPTION:
//	System interface, sound.
//
//-----------------------------------------------------------------------------



import data.sfxinfo_t;


/*
// UNIX hack, to be removed.
#ifdef SNDSERV
#include <stdio.h>
extern FILE* sndserver;
extern char* sndserver_filename;
#endif*/


public interface DoomSoundInterface{


// Init at program start...
public void I_InitSound();

// ... update sound buffer and audio device at runtime...
public void I_UpdateSound();
public void I_SubmitSound();

// ... shut down and relase at program termination.
public void I_ShutdownSound();


//
//  SFX I/O
//

// Initialize channels?
void I_SetChannels();

// Get raw data lump index for sound descriptor.
public int I_GetSfxLumpNum (sfxinfo_t sfxinfo );


// Starts a sound in a particular sound channel.
public int
I_StartSound
( int		id,
  int		vol,
  int		sep,
  int		pitch,
  int		priority );


// Stops a sound channel.
public void I_StopSound(int handle);

// Called by S_*() functions
//  to see if a channel is still playing.
// Returns 0 if no longer playing, 1 if playing.
public boolean I_SoundIsPlaying(int handle);

// Updates the volume, separation,
//  and pitch of a sound channel.
public void
I_UpdateSoundParams
( int		handle,
  int		vol,
  int		sep,
  int		pitch );


//
//  MUSIC I/O
//
public void I_InitMusic();
public void I_ShutdownMusic();
// Volume.
public void I_SetMusicVolume(int volume);
// PAUSE game handling.
public void I_PauseSong(int handle);
public void I_ResumeSong(int handle);
// Registers a song handle to song data.
public int I_RegisterSong(byte[] data);
// Called by anything that wishes to start music.
//  plays a song, and when the song is done,
//  starts playing it again in an endless loop.
// Horrible thing to do, considering.
public void
I_PlaySong
( int		handle,
  int		looping );
// Stops a song over 3 seconds.
public void I_StopSong(int handle);
// See above (register), then think backwards
public void I_UnRegisterSong(int handle);
}
package i;

public enum BppMode {
    HiColor,
    Indexed,
    TrueColor,
    TrueColor32
}

package i;

public interface IDrawer {

	public void Drawer();
	
}

package i;

import doom.DoomStatus;

public interface DoomStatusAware {
	  public void updateStatus(DoomStatus<?,?> DC);
}

package i;

/** Methods specific to Doom-System video interfacing. 
 *  In essence, whatever you are using as a final system-specific way to display
 *  the screens, should be able to respond to these commands. In particular,
 *  screen update requests must be honored, and palette/gamma request changes
 *  must be intercepted before they are forwarded to the renderers (in case they
 *  are system-specific, rather than renderer-specific).
 *  
 *  The idea is that the final screen rendering module sees/handles as less as
 *  possible, and only gets a screen to render, no matter what depth it is.
 * 
 *  
 */

public interface DoomVideoInterface<K> {

	public void StartFrame();

	public void StartTic();

	public void SetPalette(int palette);

	public void InitGraphics();

	public void FinishUpdate();

	public void UpdateNoBlit();

	public void ShutdownGraphics();

	public void SetGamma(int gammalevel);
	
	public void ReadScreen(K linear);

}

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: DoomSystem.java,v 1.18 2013/06/04 11:29:39 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// $Log: DoomSystem.java,v $
// Revision 1.18  2013/06/04 11:29:39  velktron
// Shut up logger
//
// Revision 1.17  2013/06/03 10:54:11  velktron
// System interface allows for a logging subsystem, but implementation details may very well vary.
//
// Revision 1.16.2.1  2012/11/19 22:14:35  velktron
// Sync tooling shutdown.
//
// Revision 1.16  2012/11/06 16:05:29  velktron
// Variables manager now part of Main.
//
// Revision 1.15  2012/09/24 17:16:22  velktron
// Massive merge between HiColor and HEAD. There's no difference from now on, and development continues on HEAD.
//
// Revision 1.14.2.2  2012/09/17 15:57:53  velktron
// Aware of IVariablesManager
//
// Revision 1.14.2.1  2012/06/14 22:38:06  velktron
// Update to handle new disk flasher
//
// Revision 1.14  2011/10/24 02:11:27  velktron
// Stream compliancy
//
// Revision 1.13  2011/09/29 15:16:04  velktron
// Modal popup generation moved here.
//
// Revision 1.12  2011/06/12 21:54:31  velktron
// Separate music + sound closing.
//
// Revision 1.11  2011/06/05 22:52:28  velktron
// Proper audio subsystem shutdown.
//
// Revision 1.10  2011/05/29 22:15:32  velktron
// Introduced IRandom interface.
//
// Revision 1.9  2011/05/26 17:56:32  velktron
// Removed ticker functionality, moved to ITicker interface.
//
// Revision 1.8  2011/05/18 16:53:29  velktron
// Implements IDoomSystem now.
//
// Revision 1.7  2011/05/17 16:54:09  velktron
// Switched to DoomStatus
//
// Revision 1.6  2011/05/13 17:44:24  velktron
// Global error function, shutdown on demos.
//
// Revision 1.5  2011/02/11 00:11:13  velktron
// A MUCH needed update to v1.3.
//
// Revision 1.4  2010/12/15 16:12:19  velktron
// Changes in Wiper code and alternate timing method, hoping to fix the Athlon X2
//
// Revision 1.3  2010/09/24 17:58:39  velktron
// Menus and HU  functional -mostly.
//
// Revision 1.2  2010/09/23 20:36:45  velktron
// *** empty log message ***
//
// Revision 1.1  2010/09/23 15:11:57  velktron
// A bit closer...
//
// Revision 1.3  2010/09/07 16:23:00  velktron
// *** empty log message ***
//
// Revision 1.2  2010/08/30 15:53:19  velktron
// Screen wipes work...Finale coded but untested.
// GRID.WAD included for testing.
//
// Revision 1.1  2010/06/30 08:58:50  velktron
// Let's see if this stuff will finally commit....
//
//
// Most stuff is still  being worked on. For a good place to start and get an idea of what is being done, I suggest checking out the "testers" package.
//
// Revision 1.1  2010/06/29 11:07:34  velktron
// Release often, release early they say...
//
// Commiting ALL stuff done so far. A lot of stuff is still broken/incomplete, and there's still mixed C code in there. I suggest you load everything up in Eclpise and see what gives from there.
//
// A good place to start is the testers/ directory, where you  can get an idea of how a few of the implemented stuff works.
//
//
// DESCRIPTION:
//
//-----------------------------------------------------------------------------

package i;

import java.io.IOException;

import sun.misc.VM;

import awt.MsgBox;
import m.MenuMisc;
import doom.DoomMain;
import doom.DoomStatus;
import doom.ticcmd_t;
import static data.Defines.TICRATE;

public class DoomSystem implements IDoomSystem, DoomStatusAware{
 


static int	mb_used = 6;

// Even the SYSTEM needs to know about DOOM!!!!
protected DoomMain<?,?> DM;

@Override
public void
Tactile
( int	on,
  int	off,
  int	total )
{
  // UNUSED.
  on = off = total = 0;
}


public ticcmd_t	emptycmd;

@Override
public ticcmd_t	BaseTiccmd()
{
    return emptycmd;
}


@Override
public int  GetHeapSize ()
{
    return mb_used*1024*1024;
}

@Override
public byte[] ZoneBase (int	size)
{
    return (new byte[mb_used*1024*1024]);
}

//
//I_Quit
//
@Override
public void Quit ()
{

 //DM.CheckDemoStatus();
 try {
	DM.QuitNetGame ();
} catch (IOException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}
 //DM.debugEnd();
 DM.ISND.ShutdownSound();
 DM.IMUS.ShutdownMusic();
 DM.commit();
 DM.VM.SaveDefaults(DM.VM.getDefaultFile());
 DM.VI.ShutdownGraphics();
 System.exit(0);
}


/**
 * I_Init
 */
@Override
public void Init ()
{
    //TODO: InitSound();
    //TODO: InitGraphics();
}


@Override
public void WaitVBL(int count)
{
    try {
        Thread.sleep(count*1000/70);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }                                
}
@Override
public void BeginRead()
{
	if (DM.DD!=null)
	   if (!DM.DD.isReading()) {
		   // Set 8 tick reading time
		   DM.DD.setReading(8);
	   }
	   	
}

@Override
public void EndRead()
{
}

@Override
public void	AllocLow(int length)
{
 ; // Dummy
}

//
// I_Error
//
@Override
public void Error (String error, Object ... args)
{

    System.err.print("Error: ");
    System.err.printf(error,args);
    System.err.print("\n");
    //va_end (argptr);

    //fflush( stderr );

    // Shutdown. Here might be other errors.
    if (DM.demorecording)
	DM.DG.CheckDemoStatus();
    if (DM.VI!=null)
    	DM.VI.ShutdownGraphics();    
    
    try {
		DM.QuitNetGame ();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
   // DM.VI.ShutdownGraphics();
    
    System.exit(-1);
}

@Override
public void Error (String error)
{
    //va_list	argptr;

    // Message first.
    //va_start (argptr,error);
    System.err.print("Error: ");
    System.err.printf(error);
    System.err.print("\n");
    //va_end (argptr);

    //fflush( stderr );

    // Shutdown. Here might be other errors.
    //if (demorecording)
	//G_CheckDemoStatus();

    //D_QuitNetGame ();
    //I_ShutdownGraphics();
    
    System.exit(-1);
}

public DoomSystem(){
emptycmd=new ticcmd_t();
}

public static void MiscError(String error, Object ... args) {
    System.err.print("Error: ");
    System.err.printf(error);
    System.err.print("\n");    
}


@Override
public void updateStatus(DoomStatus DS) {
    this.DM=DS.DM;
    
}


// This particular implementation will generate a popup box.// 
@Override
public boolean GenerateAlert(String title,String cause) {
    MsgBox alert=new MsgBox(null, title, cause, true);
      return alert.isOk();
}

}

package i;

import java.io.IOException;

import m.IVariablesManager;
import m.VarsManager;

import rr.LightsAndColors;

import v.VideoScaleInfo;
import doom.CommandLine;
import doom.DoomMain;
import doom.ICommandLineManager;

//Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
//$Id: Main.java,v 1.14 2016/06/06 14:22:17 velktron Exp $
//
//Copyright (C) 1993-1996 by id Software, Inc.
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//
//DESCRIPTION:
//Main program, simply calls D_DoomMain high level loop after loading 
//some essential settings and determining what "flavor" we're going to run.
//
//-----------------------------------------------------------------------------



public class Main {
    static final String rcsid = "$Id: Main.java,v 1.14 2016/06/06 14:22:17 velktron Exp $";

    /** Global setting for initializing the renderer's bitplane mode */
    public static BppMode bpp;
    /** Global setting for initializing the renderer's light levels */
    public static int lightlevels;
    
    public static void main(String[] argv) throws IOException{

    	  //First, get the command line parameters.
          ICommandLineManager CLM=new CommandLine(argv);
            
          // Handles variables and settings from default.cfg
          IVariablesManager VM=new VarsManager(CLM);
          
          // load before initting other systems, but don't apply them yet.          
          System.out.print ("M_LoadDefaults: Load system defaults.\n");
          VM.LoadDefaults (VM.getDefaultFile());
        
          bpp= BppMode.Indexed;
          lightlevels=5;
          
          //if (VM.getSetting(name), value))
          
            
          if (VM.isSettingLiteral("color_depth","hicolor"))
              bpp=BppMode.HiColor;
          if (VM.isSettingLiteral("color_depth","truecolor"))
              bpp=BppMode.TrueColor;
          
          if (CLM.CheckParmBool("-hicolor")) bpp=BppMode.HiColor;
              else
          if (CLM.CheckParmBool("-truecolor")) bpp=BppMode.TrueColor;
          
          
          
          // Here we create DOOM
          DoomMain<?, ?> DM=null;
          // Create a dummy. This will force static init to run.
          
          switch(bpp){
          case Indexed:
              System.out.println("Indexed 8-bit mode selected...");
              DM=new DoomMain.Indexed();
              break;
          case HiColor:
              System.out.println("HiColor (Alpha) 16-bit mode selected...");
              DM=new DoomMain.HiColor();
              break;
          case TrueColor:
          case TrueColor32:
              System.out.println("TrueColor (extended colormaps) 24-bit mode selected...");
              DM=new DoomMain.TrueColor();
              break;

          }    

          DM.setCommandLineArgs(CLM);
          DM.registerVariableManager(VM);
          DM.Init();
          DM.Start();

          return;
        } 
    }

package i;

// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: SystemSoundInterface.java,v 1.2 2011/05/17 16:51:20 velktron Exp $
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
//
// DESCRIPTION:
//	System interface, sound.
//
//-----------------------------------------------------------------------------



import data.sfxinfo_t;


/*
// UNIX hack, to be removed.
#ifdef SNDSERV
#include <stdio.h>
extern FILE* sndserver;
extern char* sndserver_filename;
#endif*/


public interface SystemSoundInterface{


// Init at program start...
public void InitSound();

// ... update sound buffer and audio device at runtime...
public void UpdateSound();
public void SubmitSound();

// ... shut down and relase at program termination.
public void ShutdownSound();


//
//  SFX I/O
//

// Initialize channels?
void SetChannels();

// Get raw data lump index for sound descriptor.
public int GetSfxLumpNum (sfxinfo_t sfxinfo );


// Starts a sound in a particular sound channel.
public int
StartSound
( int		id,
  int		vol,
  int		sep,
  int		pitch,
  int		priority );


// Stops a sound channel.
public void StopSound(int handle);

// Called by S_*() functions
//  to see if a channel is still playing.
// Returns 0 if no longer playing, 1 if playing.
public boolean SoundIsPlaying(int handle);

// Updates the volume, separation,
//  and pitch of a sound channel.
public void
UpdateSoundParams
( int		handle,
  int		vol,
  int		sep,
  int		pitch );


//
//  MUSIC I/O
//
public void InitMusic();
public void ShutdownMusic();
// Volume.
public void SetMusicVolume(int volume);
// PAUSE game handling.
public void PauseSong(int handle);
public void ResumeSong(int handle);
// Registers a song handle to song data.
public int RegisterSong(byte[] data);
// Called by anything that wishes to start music.
//  plays a song, and when the song is done,
//  starts playing it again in an endless loop.
// Horrible thing to do, considering.
public void
PlaySong
( int		handle,
  int		looping );
// Stops a song over 3 seconds.
public void StopSong(int handle);
// See above (register), then think backwards
public void UnRegisterSong(int handle);
}

/** Blatantly ripped off Jake 2. Sieg heil! */

/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
package i;

import java.awt.event.*;
import java.util.LinkedList;

import doom.event_t;
import doom.evtype_t;

/**
 * InputListener
 */
public final class InputListener implements KeyListener, MouseListener, 
        MouseMotionListener, ComponentListener, MouseWheelListener {

    // modifications of eventQueue must be thread safe!
    private static LinkedList<event_t> eventQueue = new LinkedList<event_t>();

    static void addEvent(event_t ev) {
        synchronized (eventQueue) {
            eventQueue.addLast(ev);
        }
    }

    public static event_t nextEvent() {
        event_t ev;
        synchronized (eventQueue) {
            ev = (!eventQueue.isEmpty())?(event_t)eventQueue.removeFirst():null;
        }
        return ev;
    }

    public void keyPressed(KeyEvent e) {
        if (!((e.getModifiersEx() & InputEvent.ALT_GRAPH_DOWN_MASK) != 0)) {
            addEvent(new event_t(evtype_t.ev_keydown, e.getKeyCode()));
        }
    }

    public void keyReleased(KeyEvent e) {
        addEvent(new event_t(evtype_t.ev_keyup, e.getKeyCode()));
    }

    public void keyTyped(KeyEvent e) {
        if ((e.getModifiersEx() & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) {
            addEvent(new event_t(evtype_t.ev_keydown, e.getKeyCode()));
            addEvent(new event_t(evtype_t.ev_keyup, e.getKeyCode()));
        }       
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
        addEvent(new event_t(evtype_t.ev_mouse, e.getButton()));
    }

    public void mouseReleased(MouseEvent e) {
        addEvent(new event_t(evtype_t.ev_mouse, e.getButton()));
    }

    public void mouseDragged(MouseEvent e) {
        addEvent(new event_t(evtype_t.ev_mouse, e.getButton(),e.getX(),e.getY()));
    }

    public void mouseMoved(MouseEvent e) {
        addEvent(new event_t(evtype_t.ev_mouse, e.getButton(),e.getX(),e.getY()));
    }
    
    public void mouseWheelMoved(MouseWheelEvent e) {
        addEvent(new event_t(evtype_t.ev_mousewheel, e.getWheelRotation()));
    }   

   // Don't listen?
    public void componentHidden(ComponentEvent e) {
    }

    public void componentMoved(ComponentEvent e) {
       // addEvent(new event_t(event_t.ConfigureNotify, e));
    }

    public void componentResized(ComponentEvent e) {
      //  addEvent(new event_t(event_t.ConfigureNotify, e));
    }

    public void componentShown(ComponentEvent e) {
    //    JOGLKBD.c = e.getComponent();
    //    addEvent(new event_t(event_t.CreateNotify, e));
    }

}


package rr;

import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import p.Resettable;

import static m.fixed_t.FRACBITS;
import w.DoomIO;
import w.IPackableDoomObject;
import w.IReadableDoomObject;

/**
 * The SideDef.
 * 
 * @author admin
 */
public class side_t
        implements IReadableDoomObject, IPackableDoomObject, Resettable {
    /** (fixed_t) add this to the calculated texture column */
    public int textureoffset;

    /** (fixed_t) add this to the calculated texture top */
    public int rowoffset;

    /**
     * Texture indices. We do not maintain names here.
     */
    public short toptexture;

    public short bottomtexture;

    public short midtexture;

    /** Sector the SideDef is facing. MAES: pointer */
    public sector_t sector;

    public int sectorid;

    public int special;

    public side_t() {
    }

    public side_t(int textureoffset, int rowoffset, short toptexture,
            short bottomtexture, short midtexture, sector_t sector) {
        super();
        this.textureoffset = textureoffset;
        this.rowoffset = rowoffset;
        this.toptexture = toptexture;
        this.bottomtexture = bottomtexture;
        this.midtexture = midtexture;
        this.sector = sector;
    }

    @Override
    public void read(DataInputStream f)
            throws IOException {
        this.textureoffset = DoomIO.readLEShort(f) << FRACBITS;
        this.rowoffset = DoomIO.readLEShort(f) << FRACBITS;
        this.toptexture = DoomIO.readLEShort(f);
        this.bottomtexture = DoomIO.readLEShort(f);
        this.midtexture = DoomIO.readLEShort(f);
        // this.sectorid=f.readLEInt();

    }

    @Override
    public void pack(ByteBuffer buffer) {
        buffer.putShort((short) (textureoffset >> FRACBITS));
        buffer.putShort((short) (rowoffset >> FRACBITS));
        buffer.putShort(toptexture);
        buffer.putShort(bottomtexture);
        buffer.putShort(midtexture);
    }

    @Override
    public void reset() {
        textureoffset = 0;
        rowoffset = 0;
        toptexture = 0;
        bottomtexture = 0;
        midtexture = 0;
        sector = null;
        sectorid = 0;
        special = 0;

    }

}

package rr;

public interface IDetailAware {

    public static int HIGH_DETAIL=0;
    public static int LOW_DETAIL=1;
    void setDetail(int detailshift);
}

package rr;

import static data.Tables.ANG180;
import static data.Tables.ANG270;
import static data.Tables.ANG90;
import static data.Tables.SlopeDiv;
import static data.Tables.tantoangle;
import utils.C2JUtils;
import doom.player_t;

public class ViewVars {
    
    // Found in draw_c. Only ever used in renderer.
    public int windowx;
    public int windowy;
    public int width;
    public int height;
    
    // MAES: outsiders have no business peeking into this.
    // Or...well..maybe they do. It's only used to center the "pause" X
    // position.
    // TODO: get rid of this?
    public int scaledwidth;
    public int centerx;
    public int centery;
    
    /** Used to determine the view center and projection in view units fixed_t */
    public int centerxfrac, centeryfrac, projection;

    /** fixed_t */
    public int x, y, z;

    // MAES: an exception to strict type safety. These are used only in here,
    // anyway (?) and have no special functions.
    // Plus I must use them as indexes. angle_t
    public long angle;

    /** fixed */
    public int cos, sin;

    public player_t player;

    /** Heretic/freeview stuff? */

    public int lookdir;
    
    // 0 = high, 1 = low. Normally only the menu and the interface can change
    // that.
    public int detailshift;
    
    public int WEAPONADJUST;
    public int BOBADJUST;
	
	/**
	 * constant arrays used for psprite clipping and initializing clipping
	 */
    public short[] negonearray; // MAES: in scaling
    public short[] screenheightarray;// MAES: in scaling
    
    /** Mirrors the one in renderer... */
    public long[] xtoviewangle;
	
    public final void initNegOneArray(int screenwidth){
	       C2JUtils.memset(negonearray, (short)-1,screenwidth);
		}
    
    public final long PointToAngle(int x, int y) {
        // MAES: note how we don't use &BITS32 here. That is because
        // we know that the maximum possible value of tantoangle is angle
        // This way, we are actually working with vectors emanating
        // from our current position.
        x -= this.x;
        y -= this.y;

        if ((x == 0) && (y == 0))
            return 0;

        if (x >= 0) {
            // x >=0
            if (y >= 0) {
                // y>= 0

                if (x > y) {
                    // octant 0
                    return tantoangle[SlopeDiv(y, x)];
                } else {
                    // octant 1
                    return (ANG90 - 1 - tantoangle[SlopeDiv(x, y)]);
                }
            } else {
                // y<0
                y = -y;

                if (x > y) {
                    // octant 8
                    return (-tantoangle[SlopeDiv(y, x)]);
                } else {
                    // octant 7
                    return (ANG270 + tantoangle[SlopeDiv(x, y)]);
                }
            }
        } else {
            // x<0
            x = -x;

            if (y >= 0) {
                // y>= 0
                if (x > y) {
                    // octant 3
                    return (ANG180 - 1 - tantoangle[SlopeDiv(y, x)]);
                } else {
                    // octant 2
                    return (ANG90 + tantoangle[SlopeDiv(x, y)]);
                }
            } else {
                // y<0
                y = -y;

                if (x > y) {
                    // octant 4
                    return (ANG180 + tantoangle[SlopeDiv(y, x)]);
                } else {
                    // octant 5
                    return (ANG270 - 1 - tantoangle[SlopeDiv(x, y)]);
                }
            }
        }
        // This is actually unreachable.
        // return 0;
    }
    
    public final int getViewWindowX(){
        return windowx;
    }

    public final int getViewWindowY(){
        return windowy;
    }
        
    public final int getScaledViewWidth(){
        return scaledwidth;
    }

    public final int getScaledViewHeight() {
        return height;
    }

}

package rr;

public interface planefunction_t {

}

package rr;

import java.io.IOException;

import rr.parallel.IGetSmpColumn;

/** All texture, flat and sprite management operations should be handled
 *  by an implementing class. As of now, the renderer does both, though it's
 *  not really the most ideal.
 *  
 * @author Velktron
 *
 */

public interface TextureManager<T> extends IGetColumn<T>, IGetCachedColumn<T>,IGetSmpColumn{

    public final static String[] texturelumps={"TEXTURE1","TEXTURE2"};
    public final static int NUMTEXLUMPS=texturelumps.length;
    public final static int TEXTURE1=0;
    public final static int TEXTURE2=1;
    
	int TextureNumForName(String texname);
	
	
	/**The "num" expected here is the internal flat number,
	 * not the absolute lump number. So impement accordingly.
	 * 
	 * @param flatname
	 * @return
	 */
	int FlatNumForName(String flatname);
	
	void PrecacheLevel() throws IOException;
	
	void GenerateComposite(int tex);
	
	int getTextureheight(int texnum);	
		
	int getTextureTranslation(int texnum);
	
	int getFlatTranslation(int flatnum);
	
	void setTextureTranslation(int texnum, int amount);
	
	void setFlatTranslation(int flatnum,int amount);

	int CheckTextureNumForName(String texnamem);

	String CheckTextureNameForNum(int texnum);
	
    int getTexturewidthmask(int tex);
   
    int getTextureColumnLump(int tex, int col);
   
    char getTextureColumnOfs(int tex, int col);

    T[] getTextureComposite(int tex);

    T getTextureComposite(int tex, int col);

    void InitFlats();

    void InitTextures() throws IOException;

    //int getFirstFlat();

    int getSkyTextureMid();

    int getSkyFlatNum();

    int getSkyTexture();

    void setSkyTexture(int skytexture);

    int InitSkyMap();

    void setSkyFlatNum(int skyflatnum);

    void GenerateLookup(int texnum)
            throws IOException;
    
    int getFlatLumpNum(int flatnum);


	T getRogueColumn(int lump, int column);

    patch_t getMaskedComposite(int tex);


    void GenerateMaskedComposite(int texnum);
    
    /** Return a "sanitized" patch. If data is insufficient, return
     *  a default patch or attempt a partial draw.
     * 
     * @param patchnum
     * @return
     */
    
    public T getSafeFlat(int flatnum);


    column_t GetColumnStruct(int tex, int col);


    void setSMPVars(int nUMMASKEDTHREADS);
    
    }

package rr;

import static rr.line_t.*;
import static data.Defines.ANGLETOSKYSHIFT;
import static data.Defines.NF_SUBSECTOR;
import static data.Defines.PU_CACHE;
import static data.Defines.SIL_BOTH;
import static data.Defines.SIL_BOTTOM;
import static data.Defines.SIL_TOP;
import static data.Limits.MAXHEIGHT;
import static data.Limits.MAXSEGS;
import static data.Limits.MAXWIDTH;
import static data.Tables.ANG180;
import static data.Tables.ANG270;
import static data.Tables.ANG90;
import static data.Tables.ANGLETOFINESHIFT;
import static data.Tables.BITS32;
import static data.Tables.DBITS;
import static data.Tables.FINEANGLES;
import static data.Tables.QUARTERMARK;
import static data.Tables.SlopeDiv;
import static data.Tables.addAngles;
import static data.Tables.finecosine;
import static data.Tables.finesine;
import static data.Tables.finetangent;
import static data.Tables.tantoangle;
import static m.BBox.BOXBOTTOM;
import static m.BBox.BOXLEFT;
import static m.BBox.BOXRIGHT;
import static m.BBox.BOXTOP;
import static m.fixed_t.FRACBITS;
import static m.fixed_t.FRACUNIT;
import static m.fixed_t.FixedDiv;
import static m.fixed_t.FixedMul;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import m.IDoomMenu;
import m.MenuMisc;
import p.AbstractLevelLoader;
import p.UnifiedGameMap;
import p.mobj_t;
import rr.UnifiedRenderer.Segs;
import rr.drawfuns.ColFuncs;
import rr.drawfuns.ColVars;
import rr.drawfuns.DoomColumnFunction;
import rr.drawfuns.DoomSpanFunction;
import rr.drawfuns.R_DrawColumnBoom;
import rr.drawfuns.R_DrawColumnBoomLow;
import rr.drawfuns.R_DrawColumnBoomOpt;
import rr.drawfuns.R_DrawColumnBoomOptLow;
import rr.drawfuns.R_DrawFuzzColumn;
import rr.drawfuns.R_DrawFuzzColumnLow;
import rr.drawfuns.R_DrawSpanLow;
import rr.drawfuns.R_DrawSpanUnrolled;
import rr.drawfuns.R_DrawTLColumn;
import rr.drawfuns.R_DrawTranslatedColumn;
import rr.drawfuns.R_DrawTranslatedColumnLow;
import rr.drawfuns.SpanVars;
import i.IDoomSystem;
import utils.C2JUtils;
import v.DoomVideoRenderer;
import v.IVideoScale;
import v.IVideoScaleAware;
import w.IWadLoader;
import data.Defines;
import data.Tables;
import doom.DoomMain;
import doom.DoomStatus;
import doom.IDoomGameNetworking;
import doom.player_t;
import doom.think_t;
import doom.thinker_t;
import static rr.LightsAndColors.*;

/**
 * Most shared -essential- status information, methods and classes related to
 * the software rendering subsystem are found here, shared between the various
 * implementations of the Doom's renderer. Not the cleanest or more OO way
 * possible, but still a good way to avoid duplicating common code. Some stuff
 * like Texture, Flat and Sprite management are also found -or at least
 * implemented temporarily- here, until a cleaner split can be made. This is a
 * kind of "Jack of all trades" class, but hopefully not for long.
 * 
 * @author velktron
 */

public abstract class RendererState<T, V>
        implements Renderer<T, V>, ILimitResettable {

    protected static final boolean DEBUG = false;

    protected static final boolean DEBUG2 = false;

    // ///////////////////// STATUS ////////////////////////

    protected DoomMain<T, V> DM;

    protected IDoomGameNetworking DGN;

    protected AbstractLevelLoader LL;

    protected ISegDrawer MySegs;

    protected IDoomMenu Menu;

    protected BSP MyBSP;

    protected PlaneDrawer<T, V> MyPlanes;

    protected IMaskedDrawer<T, V> MyThings;

    protected DoomVideoRenderer<T, V> V;

    protected UnifiedGameMap P;

    public IWadLoader W;

    public ISpriteManager SM;

    public IVisSpriteManagement<V> VIS;

    public IDoomSystem I;

    protected TextureManager<T> TexMan;

    public ViewVars view;

    public LightsAndColors<V> colormaps;

    public SegVars seg_vars;

    public Visplanes vp_vars;

    // Rendering subsystems that are detailshift-aware

    protected List<IDetailAware> detailaware;

    // The only reason to query scaledviewwidth from outside the renderer, is
    // this.
    public boolean isFullHeight() {
        return (view.height == SCREENHEIGHT);
    }

    public boolean isFullWidth() {
        return (view.scaledwidth == SCREENWIDTH);
    }

    public boolean isFullScreen() {
        return isFullWidth() && isFullHeight();
    }

    /**
     * Increment every time a check is made For some reason, this needs to be
     * visible even by enemies thinking :-S
     */
    protected int validcount = 1;

    /** Who can set this? A: The Menu. */
    protected boolean setsizeneeded;

    protected int setblocks;

    protected int setdetail;

    // private BSPVars bspvars;

    /**
     * R_SetViewSize Do not really change anything here, because it might be in
     * the middle of a refresh. The change will take effect next refresh.
     * 
     * @param blocks
     *        11 is full screen, 9 default.
     * @param detail
     *        0= high, 1 =low.
     */

    public void SetViewSize(int blocks, int detail) {
        // System.out.println("SetViewSize");
        setsizeneeded = true;
        setblocks = blocks;
        setdetail = detail;

        for (IDetailAware d : detailaware) {
            d.setDetail(setdetail);
        }
    }

    /**
     * R_SetupFrame
     */
    public void SetupFrame(player_t player) {
        int i;

        view.player = player;
        view.x = player.mo.x;
        view.y = player.mo.y;
        // viewangle = addAngles(player.mo.angle , viewangleoffset);
        view.angle = player.mo.angle & BITS32;
        // With 32 colormaps, a bump of 1 or 2 is normal.
        // With more than 32, it should be obviously higher.

        int bumplight = Math.max(LBITS - 5, 0);
        // Be a bit more generous, otherwise the effect is not
        // as evident with truecolor maps.
        bumplight += (bumplight > 0) ? 1 : 0;

        colormaps.extralight = player.extralight << bumplight;

        view.z = player.viewz;
        view.lookdir = (int) player.lookdir;
        int tempCentery;

        // MAES: hacks based on Heretic. Weapon movement needs to be compensated
        if (setblocks == 11)
            tempCentery =
                (view.height / 2)
                        + (int) (view.lookdir * SCREEN_MUL * setblocks) / 11;
        else
            tempCentery =
                (view.height / 2)
                        + (int) (view.lookdir * SCREEN_MUL * setblocks) / 10;

        if (view.centery != tempCentery) {
            view.centery = tempCentery;
            view.centeryfrac = view.centery << FRACBITS;
            int yslope[] = vp_vars.yslope;
            for (i = 0; i < view.height; i++) {
                yslope[i] =
                    FixedDiv(
                        (view.width << view.detailshift) / 2 * FRACUNIT,
                        Math.abs(((i - view.centery) << FRACBITS) + FRACUNIT
                                / 2));
            }

            skydcvars.centery =
                maskedcvars.centery = dcvars.centery = view.centery;
        }

        view.sin = Tables.finesine(view.angle);
        view.cos = Tables.finecosine(view.angle);

        sscount = 0;

        if (player.fixedcolormap != 0) {
            colormaps.fixedcolormap = colormaps.colormaps[player.fixedcolormap];
            // Offset by fixedcolomap
            // pfixedcolormap =player.fixedcolormap*256;

            colormaps.walllights = colormaps.scalelightfixed;

            for (i = 0; i < MAXLIGHTSCALE; i++)
                colormaps.scalelightfixed[i] = colormaps.fixedcolormap;
        } else
            colormaps.fixedcolormap = null;

        framecount++;
        validcount++;
    }

    /**
     * R_SetupFrame for a particular actor.
     */
    public void SetupFrame(mobj_t actor) {

        // viewplayer = player;
        view.x = actor.x;
        view.y = actor.y;
        // viewangle = addAngles(player.mo.angle , viewangleoffset);
        view.angle = actor.angle & BITS32;
        // extralight = actor.extralight;

        view.z = actor.z + actor.height;

        view.sin = finesine(view.angle);
        view.cos = finecosine(view.angle);

        sscount = 0;

        framecount++;
        validcount++;
    }

    public RendererState(DoomStatus<T, V> DS) {
        this.updateStatus(DS);

        // These don't change between implementations, yet.
        this.MyBSP = new BSP();

        this.view = new ViewVars();
        this.seg_vars = new SegVars();
        this.dcvars=new ColVars<T,V>();
        this.dsvars=new SpanVars<T,V>();        
        this.maskedcvars=new ColVars<T,V>();
        this.skydcvars=new ColVars<T,V>();
        this.colfunclow=new ColFuncs<T,V>();
        this.colfunchi=new ColFuncs<T,V>();

        this.detailaware = new ArrayList<IDetailAware>();
        this.colormaps=new LightsAndColors<V>();
        // It's better to construct this here
        this.TexMan = (TextureManager<T>) new SimpleTextureManager(DS);
        this.SM=new SpriteManager(DS);

        // Visplane variables
        this.vp_vars = new Visplanes(view, TexMan);
        // Initialize array of minus ones for sprite clipping
        view.initNegOneArray(SCREENWIDTH);

        // Set rendering functions only after screen sizes
        // and stuff have been set.
        
        this.MyPlanes = new Planes(this);
        this.VIS=new VisSprites<V>(this);
        this.MyThings = new SimpleThings<T,V>(this);
        
    }

    @SuppressWarnings("unchecked")
    @Override
    public void updateStatus(DoomStatus<?, ?> DC) {
        this.DM = (DoomMain<T, V>) DC.DM;
        this.DGN = DC.DGN;
        this.LL = DC.LL;
        this.W = DC.W;
        this.P = DC.P;
        // We must also connect screen to V. Don't forget it. Do it in Init(),
        // OK?
        this.V = (DoomVideoRenderer<T, V>) DC.V;
        this.SM = DC.SM;
        this.I = DC.I;
        if (VIS != null)
            this.VIS.updateStatus(this);
    }

    // ////////////////////////////// THINGS ////////////////////////////////

    protected final class BSP
            extends BSPVars {

        /** newend is one past the last valid seg (cliprange_t) */
        int newend;

        cliprange_t[] solidsegs;

        public BSP() {
            solidsegs = new cliprange_t[MAXSEGS + 1];
            C2JUtils.initArrayOfObjects(solidsegs);

        }

        /**
         * R_ClipSolidWallSegment Does handle solid walls, single sided LineDefs
         * (middle texture) that entirely block the view VERTICALLY. Handles
         * "clipranges" for a solid wall, aka where it blocks the view.
         * 
         * @param first
         *        starting y coord?
         * @param last
         *        ending y coord?
         */

        private void ClipSolidWallSegment(int first, int last) {

            int next;
            int start;
            // int maxlast=Integer.MIN_VALUE;

            start = 0; // within solidsegs

            // Find the first cliprange that touches the range.
            // Actually, the first one not completely hiding it (its last must
            // be lower than first.

            while (solidsegs[start].last < first - 1)
                start++;

            // If the post begins above the lastly found cliprange...
            if (first < solidsegs[start].first) {
                // ..and ends above it, too (no overlapping)
                if (last < solidsegs[start].first - 1) {
                    // ... then the post is entirely visible (above start),
                    // so insert a new clippost. Calling this function
                    // tells the renderer that there is an obstruction.
                    MySegs.StoreWallRange(first, last);

                    // Newend should have a value of 2 if we are at the
                    // beginning of a new frame.
                    next = newend;
                    newend++;

                    if (next >= solidsegs.length)
                        ResizeSolidSegs();
                    while (next != start) {
                        // *next=*(next-1);
                        /*
                         * MAES: I think this is supposed to copy the structs
                         * solidsegs[next] = solidsegs[next-1].clone(); OK, so
                         * basically the last solidseg copies its previous, and
                         * so on until we reach the start. This means that at
                         * some point, the value of the start solidseg is
                         * duplicated.
                         */

                        solidsegs[next].copy(solidsegs[next - 1]);

                        next--;
                    }

                    // At this point, next points at start.
                    // Therefore, start
                    solidsegs[next].first = first;
                    solidsegs[next].last = last;
                    return;
                }

                // There is a fragment above *start. This can occur if it a
                // post does start before another, but its lower edge overlaps
                // (partial, upper occlusion)
                MySegs.StoreWallRange(first, solidsegs[start].first - 1);
                // Now adjust the clip size.
                solidsegs[start].first = first;
            }

            // We can reach this only if a post starts AFTER another

            // Bottom contained in start? Obviously it won't be visible.
            if (last <= solidsegs[start].last)
                return;

            next = start;
            while (last >= solidsegs[(next + 1)].first - 1) {
                // There is a fragment between two posts.
                MySegs.StoreWallRange(solidsegs[next].last + 1,
                    solidsegs[next + 1].first - 1);
                next++;

                if (last <= solidsegs[next].last) {
                    // Bottom is contained in next.
                    // Adjust the clip size.
                    solidsegs[start].last = solidsegs[next].last;
                    // goto crunch;

                    { // crunch code
                        if (next == start) {
                            // Post just extended past the bottom of one post.
                            return;
                        }

                        while (next++ != newend) {
                            // Remove a post.
                            // MAES: this is a struct copy.
                            if (next >= solidsegs.length)
                                ResizeSolidSegs();
                            solidsegs[++start].copy(solidsegs[next]);
                        }

                        newend = start + 1;
                        return;
                    }
                }
            }

            // There is a fragment after *next.
            MySegs.StoreWallRange(solidsegs[next].last + 1, last);
            // Adjust the clip size.
            solidsegs[start].last = last;

            // Remove start+1 to next from the clip list,
            // because start now covers their area.

            { // crunch code
                if (next == start) {
                    // Post just extended past the bottom of one post.
                    return;
                }

                while (next++ != newend) {
                    // Remove a post.
                    // MAES: this is a struct copy.
                    // MAES: this can overflow, breaking e.g. MAP30 of Final
                    // Doom.
                    if (next >= solidsegs.length)
                        ResizeSolidSegs();
                    solidsegs[++start].copy(solidsegs[next]);
                }

                newend = start + 1;
                return;
            }
        }

        protected final void ResizeSolidSegs() {
            solidsegs = C2JUtils.resize(solidsegs, solidsegs.length * 2);
        }

        //
        // R_ClipPassWallSegment
        // Clips the given range of columns,
        // but does not includes it in the clip list.
        // Does handle windows,
        // e.g. LineDefs with upper and lower texture.
        //
        private void ClipPassWallSegment(int first, int last) {

            // Find the first range that touches the range
            // (adjacent pixels are touching).
            int start = 0;

            while (solidsegs[start].last < first - 1)
                start++;

            if (first < solidsegs[start].first) {
                if (last < solidsegs[start].first - 1) {
                    // Post is entirely visible (above start).
                    MySegs.StoreWallRange(first, last);
                    return;
                }

                // There is a fragment above *start.
                MySegs.StoreWallRange(first, solidsegs[start].first - 1);
            }

            // Bottom contained in start?
            if (last <= solidsegs[start].last)
                return;

            // MAES: Java absolutely can't do without a sanity check here.
            // if (startptr>=MAXSEGS-2) return;

            while (last >= solidsegs[start + 1].first - 1) {
                // There is a fragment between two posts.
                MySegs.StoreWallRange(solidsegs[start].last + 1,
                    solidsegs[start + 1].first - 1);
                start++;
                // if (startptr>=MAXSEGS-2) return;
                // start=solidsegs[startptr];

                if (last <= solidsegs[start].last)
                    return;
            }

            // There is a fragment after *next.
            MySegs.StoreWallRange(solidsegs[start].last + 1, last);
        }

        /**
         * R_ClearClipSegs Clears the clipping segs list. The list is actually
         * fixed size for efficiency reasons, so it just tells Doom to use the
         * first two solidsegs, which are "neutered". It's interesting to note
         * how the solidsegs begin and end just "outside" the visible borders of
         * the screen.
         */

        public void ClearClipSegs() {
            solidsegs[0].first = -0x7fffffff;
            solidsegs[0].last = -1;
            solidsegs[1].first = view.width;
            solidsegs[1].last = 0x7fffffff;
            newend = 2; // point so solidsegs[2];
        }

        /**
         * R_AddLine Called after a SubSector BSP trasversal ends up in a
         * "final" subsector. Clips the given segment and adds any visible
         * pieces to the line list. It also determines what kind of boundary
         * (line) visplane clipping should be performed. E.g. window, final
         * 1-sided line, closed door etc.) CAREFUL: was the source of much
         * frustration with visplanes...
         */
        private void AddLine(seg_t line) {
            if (DEBUG)
                System.out.println("Entered AddLine for " + line);
            int x1;
            int x2;
            long angle1;
            long angle2;
            long span;
            long tspan;

            curline = line;

            // OPTIMIZE: quickly reject orthogonal back sides.
            angle1 = view.PointToAngle(line.v1x, line.v1y);
            angle2 = view.PointToAngle(line.v2x, line.v2y);

            // Clip to view edges.
            // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW).

            span = addAngles(angle1, -angle2);

            // Back side? I.e. backface culling?
            if (span >= ANG180)
                return;

            // Global angle needed by segcalc.
            MySegs.setGlobalAngle(angle1);
            angle1 -= view.angle;
            angle2 -= view.angle;

            angle1 &= BITS32;
            angle2 &= BITS32;

            tspan = addAngles(angle1, clipangle);

            if (tspan > CLIPANGLE2) {
                tspan -= CLIPANGLE2;
                tspan &= BITS32;

                // Totally off the left edge?
                if (tspan >= span)
                    return;

                angle1 = clipangle;
            }
            tspan = addAngles(clipangle, -angle2);

            if (tspan > CLIPANGLE2) {
                tspan -= CLIPANGLE2;
                tspan &= BITS32;

                // Totally off the left edge?
                if (tspan >= span)
                    return;
                angle2 = -clipangle;
                angle2 &= BITS32;
            }

            // The seg is in the view range,
            // but not necessarily visible.

            angle1 = ((angle1 + ANG90) & BITS32) >>> ANGLETOFINESHIFT;
            angle2 = ((angle2 + ANG90) & BITS32) >>> ANGLETOFINESHIFT;
            x1 = viewangletox[(int) angle1];
            x2 = viewangletox[(int) angle2];

            // Does not cross a pixel?
            if (x1 == x2)
                return;

            backsector = line.backsector;

            // Single sided line?

            if (backsector == null) {
                if (DEBUG)
                    System.out
                            .println("Entering ClipSolidWallSegment SS with params "
                                    + x1 + " " + (x2 - 1));
                ClipSolidWallSegment(x1, x2 - 1); // to clipsolid
                if (DEBUG)
                    System.out.println("Exiting ClipSolidWallSegment");
                return;
            }

            // Closed door.
            if (backsector.ceilingheight <= frontsector.floorheight
                    || backsector.floorheight >= frontsector.ceilingheight) {
                if (DEBUG)
                    System.out
                            .println("Entering ClipSolidWallSegment Closed door with params "
                                    + x1 + " " + (x2 - 1));
                ClipSolidWallSegment(x1, x2 - 1);
                ; // to clipsolid
                return;
            }

            // Window. This includes same-level floors with different textures
            if (backsector.ceilingheight != frontsector.ceilingheight
                    || backsector.floorheight != frontsector.floorheight) {
                if (DEBUG)
                    System.out
                            .println("Entering ClipSolidWallSegment window with params "
                                    + x1 + " " + (x2 - 1));
                ClipPassWallSegment(x1, x2 - 1); // to clippass
                return;
            }

            // Reject empty lines used for triggers
            // and special events.
            // Identical floor and ceiling on both sides,
            // identical light levels on both sides,
            // and no middle texture.
            if (backsector.ceilingpic == frontsector.ceilingpic
                    && backsector.floorpic == frontsector.floorpic
                    && backsector.lightlevel == frontsector.lightlevel
                    && curline.sidedef.midtexture == 0) {
                return;
            }

            // If nothing of the previous holds, then we are
            // treating the case of same-level, differently
            // textured floors. ACHTUNG, this caused the "bleeding floor"
            // bug, which is now fixed.
            // Fucking GOTOs....
            ClipPassWallSegment(x1, x2 - 1); // to clippass
            if (DEBUG)
                System.out.println("Exiting AddLine for " + line);
        }

        //
        // R_CheckBBox
        // Checks BSP node/subtree bounding box.
        // Returns true
        // if some part of the bbox might be visible.
        //
        private int[][] checkcoord = { { 3, 0, 2, 1 }, { 3, 0, 2, 0 },
                { 3, 1, 2, 0 }, { 0 }, { 2, 0, 2, 1 }, { 0, 0, 0, 0 },
                { 3, 1, 3, 0 }, { 0 }, { 2, 0, 3, 1 }, { 2, 1, 3, 1 },
                { 2, 1, 3, 0 } };

        /**
         * @param bspcoord
         *        (fixed_t* as bbox)
         * @return
         */
        public boolean CheckBBox(int[] bspcoord) {
            int boxx;
            int boxy;
            int boxpos;

            // fixed_t
            int x1;
            int y1;
            int x2;
            int y2;

            // angle_t
            long angle1;
            long angle2;
            long span;
            long tspan;

            cliprange_t start;

            int sx1;
            int sx2;

            // Find the corners of the box
            // that define the edges from current viewpoint.
            if (view.x <= bspcoord[BOXLEFT])
                boxx = 0;
            else if (view.x < bspcoord[BOXRIGHT])
                boxx = 1;
            else
                boxx = 2;

            if (view.y >= bspcoord[BOXTOP])
                boxy = 0;
            else if (view.y > bspcoord[BOXBOTTOM])
                boxy = 1;
            else
                boxy = 2;

            boxpos = (boxy << 2) + boxx;
            if (boxpos == 5)
                return true;

            x1 = bspcoord[checkcoord[boxpos][0]];
            y1 = bspcoord[checkcoord[boxpos][1]];
            x2 = bspcoord[checkcoord[boxpos][2]];
            y2 = bspcoord[checkcoord[boxpos][3]];

            // check clip list for an open space
            angle1 = view.PointToAngle(x1, y1) - view.angle;
            angle2 = view.PointToAngle(x2, y2) - view.angle;

            angle1 &= BITS32;
            angle2 &= BITS32;

            span = angle1 - angle2;

            span &= BITS32;

            // Sitting on a line?
            if (span >= ANG180)
                return true;

            tspan = angle1 + clipangle;
            tspan &= BITS32;

            if (tspan > CLIPANGLE2) {
                tspan -= CLIPANGLE2;
                tspan &= BITS32;
                // Totally off the left edge?
                if (tspan >= span)
                    return false;

                angle1 = clipangle;
            }
            tspan = (clipangle - angle2) & BITS32;
            ;
            if (tspan > CLIPANGLE2) {
                tspan -= CLIPANGLE2;
                tspan &= BITS32;

                // Totally off the left edge?
                if (tspan >= span)
                    return false;

                angle2 = -clipangle;
                angle2 &= BITS32;
            }

            // Find the first clippost
            // that touches the source post
            // (adjacent pixels are touching).
            angle1 = ((angle1 + ANG90) & BITS32) >>> ANGLETOFINESHIFT;
            angle2 = ((angle2 + ANG90) & BITS32) >>> ANGLETOFINESHIFT;
            sx1 = viewangletox[(int) angle1];
            sx2 = viewangletox[(int) angle2];

            // Does not cross a pixel.
            if (sx1 == sx2)
                return false;
            sx2--;

            int pstart = 0;
            start = solidsegs[pstart];
            // FIXME: possible solidseg overflow here overflows
            while (start.last < sx2 && pstart < MAXSEGS)
                start = solidsegs[pstart++];

            if (sx1 >= start.first && sx2 <= start.last) {
                // The clippost contains the new span.
                return false;
            }

            return true;
        }

        /**
         * R_Subsector Determine floor/ceiling planes. Add sprites of things in
         * sector. Draw one or more line segments. It also alters the visplane
         * list!
         * 
         * @param num
         *        Subsector from subsector_t list in Lever Loader.
         */

        private void Subsector(int num) {
            if (DEBUG)
                System.out.println("\t\tSubSector " + num + " to render");
            int count;
            int line; // pointer into a list of segs instead of seg_t
            subsector_t sub;

            if (RANGECHECK) {
                if (num >= LL.numsubsectors)
                    I.Error("R_Subsector: ss %d with numss = %d", num,
                        LL.numsubsectors);
            }

            sscount++;
            sub = LL.subsectors[num];

            frontsector = sub.sector;
            if (DEBUG)
                System.out.println("Frontsector to render :" + frontsector);
            count = sub.numlines;
            // line = LL.segs[sub.firstline];
            line = sub.firstline;

            if (DEBUG)
                System.out
                        .println("Trying to find an existing FLOOR visplane...");
            if (frontsector.floorheight < view.z) {
                vp_vars.floorplane =
                    vp_vars.FindPlane(frontsector.floorheight,
                        frontsector.floorpic, frontsector.lightlevel);
            } else
                // FIXME: unclear what would happen with a null visplane used
                // It's never checked explicitly for either condition, just
                // called straight.
                vp_vars.floorplane = -1; // in lieu of NULL

            // System.out.println("Trying to find an existing CEILING visplane...");

            if (frontsector.ceilingheight > view.z
                    || frontsector.ceilingpic == TexMan.getSkyFlatNum()) {
                vp_vars.ceilingplane =
                    vp_vars.FindPlane(frontsector.ceilingheight,
                        frontsector.ceilingpic, frontsector.lightlevel);
            } else
                vp_vars.ceilingplane = -1; // In lieu of NULL. Will bomb if
                                           // actually
            // used.

            VIS.AddSprites(frontsector);

            if (DEBUG)
                System.out.println("Enter Addline for SubSector " + num
                        + " count " + count);
            while (count-- > 0) {
                AddLine(LL.segs[line]);
                line++;
            }
            if (DEBUG)
                System.out.println("Exit Addline for SubSector " + num);
        }

        /**
         * RenderBSPNode Renders all subsectors below a given node, traversing
         * subtree recursively. Just call with BSP root.
         */
        public void RenderBSPNode(int bspnum) {
            if (DEBUG)
                System.out.println("Processing BSP Node " + bspnum);

            node_t bsp;
            int side;

            // Found a subsector? Then further decisions are taken, in, well,
            // SubSector.
            if (C2JUtils.flags(bspnum, NF_SUBSECTOR)) {
                if (DEBUG)
                    System.out.println("Subsector found.");
                if (bspnum == -1)
                    Subsector(0);
                else
                    Subsector(bspnum & (~NF_SUBSECTOR));
                return;
            }

            bsp = LL.nodes[bspnum];

            // Decide which side the view point is on.
            side = bsp.PointOnSide(view.x, view.y);
            if (DEBUG)
                System.out.println("\tView side: " + side);

            // Recursively divide front space.
            if (DEBUG)
                System.out.println("\tEnter Front space of " + bspnum);
            RenderBSPNode(bsp.children[side]);
            if (DEBUG)
                System.out.println("\tReturn Front space of " + bspnum);

            // Possibly divide back space.

            if (CheckBBox(bsp.bbox[side ^ 1].bbox)) {
                if (DEBUG)
                    System.out.println("\tEnter Back space of " + bspnum);
                RenderBSPNode(bsp.children[side ^ 1]);
                if (DEBUG)
                    System.out.println("\tReturn Back space of " + bspnum);
            }
        }

    }

    protected abstract class SegDrawer
            implements ISegDrawer {

        protected static final int HEIGHTBITS = 12;

        protected static final int HEIGHTUNIT = (1 << HEIGHTBITS);

        protected final Visplanes vp_vars;

        protected final SegVars seg_vars;

        // Fast blanking buffers.
        protected short[] BLANKFLOORCLIP;

        protected short[] BLANKCEILINGCLIP;

        @Override
        public short[] getBLANKFLOORCLIP() {
            return BLANKFLOORCLIP;
        }

        @Override
        public short[] getBLANKCEILINGCLIP() {
            return BLANKCEILINGCLIP;
        }

        /** fixed_t */
        protected int pixhigh, pixlow, pixhighstep, pixlowstep, topfrac,
                topstep, bottomfrac, bottomstep;

        protected int worldtop, worldbottom, worldhigh, worldlow;

        /** True if any of the segs textures might be visible. */
        protected boolean segtextured;

        /**
         * Clip values are the solid pixel bounding the range. floorclip starts
         * out SCREENHEIGHT ceilingclip starts out -1
         */
        protected short[] floorclip, ceilingclip;

        public final short[] getFloorClip() {
            return floorclip;
        }

        public final short[] getCeilingClip() {
            return ceilingclip;
        }

        /** False if the back side is the same plane. */
        protected boolean markfloor, markceiling;

        protected boolean maskedtexture;

        protected int toptexture;

        protected int bottomtexture;

        protected int midtexture;

        /** angle_t, used after adding ANG90 in StoreWallRange */
        protected long rw_normalangle;

        /** angle to line origin */
        protected long rw_angle1;

        //
        // regular wall
        //
        protected int rw_x;

        protected int rw_stopx;

        protected long rw_centerangle; // angle_t

        /** fixed_t */
        protected int rw_offset, rw_distance, rw_scale, rw_scalestep,
                rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid;

        public void resetLimits() {
            drawseg_t[] tmp = new drawseg_t[seg_vars.MAXDRAWSEGS];
            System.arraycopy(seg_vars.drawsegs, 0, tmp, 0, seg_vars.MAXDRAWSEGS);

            // Now, that was quite a haircut!.
            seg_vars.drawsegs = tmp;

            // System.out.println("Drawseg buffer cut back to original limit of "+MAXDRAWSEGS);
        }
        
        public void sync(){
            // Nothing required if serial.
        }

        /**
         * R_StoreWallRange A wall segment will be drawn between start and stop
         * pixels (inclusive). This is the only place where
         * markceiling/markfloor can be set. Can only be called from
         * ClipSolidWallSegment and ClipPassWallSegment.
         * 
         * @throws IOException
         */

        public void StoreWallRange(int start, int stop) {

            if (DEBUG2)
                System.out.println("\t\t\t\tStorewallrange called between "
                        + start + " and " + stop);

            int hyp; // fixed_t
            int sineval; // fixed_t
            int distangle;
            long offsetangle; // angle_t
            int vtop; // fixed_t
            int lightnum;
            drawseg_t seg;

            // don't overflow and crash
            if (seg_vars.ds_p == seg_vars.drawsegs.length)
                seg_vars.ResizeDrawsegs();

            if (RANGECHECK) {
                if (start >= view.width || start > stop)
                    I.Error("Bad R_RenderWallRange: %d to %d", start, stop);
            }

            seg = seg_vars.drawsegs[seg_vars.ds_p];

            MyBSP.sidedef = MyBSP.curline.sidedef;
            MyBSP.linedef = MyBSP.curline.linedef;

            // mark the segment as visible for auto map
            MyBSP.linedef.flags |= ML_MAPPED;

            // calculate rw_distance for scale calculation
            rw_normalangle = addAngles(MyBSP.curline.angle, ANG90);

            /*
             * MAES: ok, this is a tricky spot. angle_t's are supposed to be
             * always positive 32-bit unsigned integers, so a subtraction should
             * be always positive by definition, right? WRONG: this fucking spot
             * caused "blind spots" at certain angles because ONLY HERE angles
             * are supposed to be treated as SIGNED and result in differences
             * <180 degrees -_- The only way to coerce this behavior is to cast
             * both as signed ints.
             */
            offsetangle = Math.abs((int) rw_normalangle - (int) rw_angle1);

            if (offsetangle > ANG90)
                offsetangle = ANG90;

            // It should fit even in a signed int, by now.
            distangle = (int) (ANG90 - offsetangle);
            hyp = PointToDist(MyBSP.curline.v1x, MyBSP.curline.v1y);
            sineval = finesine(distangle);
            rw_distance = FixedMul(hyp, sineval);

            seg.x1 = rw_x = start;
            seg.x2 = stop;
            seg.curline = MyBSP.curline;
            /*
             * This is the only place it's ever explicitly assigned. Therefore
             * it always starts at stop+1.
             */
            rw_stopx = stop + 1;

            // calculate scale at both ends and step
            // this is the ONLY place where rw_scale is set.
            seg.scale1 =
                rw_scale =
                    ScaleFromGlobalAngle((view.angle + xtoviewangle[start]));

            if (stop > start) {
                seg.scale2 =
                    ScaleFromGlobalAngle(view.angle + xtoviewangle[stop]);
                seg.scalestep =
                    rw_scalestep = (seg.scale2 - rw_scale) / (stop - start);
            } else {
                // UNUSED: try to fix the stretched line bug
                /*
                 * #if 0 if (rw_distance < FRACUNIT/2) { fixed_t trx,try;
                 * fixed_t gxt,gyt; trx = curline.v1.x - viewx; try =
                 * curline.v1.y - viewy; gxt = FixedMul(trx,viewcos); gyt =
                 * -FixedMul(try,viewsin); seg.scale1 = FixedDiv(projection,
                 * gxt-gyt)<<detailshift; } #endif
                 */
                seg.scale2 = seg.scale1;
            }

            // calculate texture boundaries
            // and decide if floor / ceiling marks are needed
            worldtop = MyBSP.frontsector.ceilingheight - view.z;
            worldbottom = MyBSP.frontsector.floorheight - view.z;

            midtexture = toptexture = bottomtexture = 0;
            maskedtexture = false;
            seg.setMaskedTextureCol(null, 0);
            // seg.maskedtexturecol = null;

            if (MyBSP.backsector == null) {
                // single sided line
                midtexture =
                    TexMan.getTextureTranslation(MyBSP.sidedef.midtexture);
                // a single sided line is terminal, so it must mark ends
                markfloor = markceiling = true;
                if ((MyBSP.linedef.flags & ML_DONTPEGBOTTOM) != 0) {
                    vtop =
                        MyBSP.frontsector.floorheight
                                + TexMan.getTextureheight(MyBSP.sidedef.midtexture);
                    // bottom of texture at bottom
                    rw_midtexturemid = vtop - view.z;
                } else {
                    // top of texture at top
                    rw_midtexturemid = worldtop;
                }
                rw_midtexturemid += MyBSP.sidedef.rowoffset;

                seg.silhouette = SIL_BOTH;
                seg.setSprTopClip(view.screenheightarray, 0);
                seg.setSprBottomClip(view.negonearray, 0);
                seg.bsilheight = Integer.MAX_VALUE;
                seg.tsilheight = Integer.MIN_VALUE;
            } else {
                // two sided line
                seg.setSprTopClip(null, 0);
                seg.setSprBottomClip(null, 0);
                seg.silhouette = 0;

                if (MyBSP.frontsector.floorheight > MyBSP.backsector.floorheight) {
                    seg.silhouette = SIL_BOTTOM;
                    seg.bsilheight = MyBSP.frontsector.floorheight;
                } else if (MyBSP.backsector.floorheight > view.z) {
                    seg.silhouette = SIL_BOTTOM;
                    seg.bsilheight = Integer.MAX_VALUE;
                    // seg.sprbottomclip = negonearray;
                }

                if (MyBSP.frontsector.ceilingheight < MyBSP.backsector.ceilingheight) {
                    seg.silhouette |= SIL_TOP;
                    seg.tsilheight = MyBSP.frontsector.ceilingheight;
                } else if (MyBSP.backsector.ceilingheight < view.z) {
                    seg.silhouette |= SIL_TOP;
                    seg.tsilheight = Integer.MIN_VALUE;
                    // seg.sprtopclip = screenheightarray;
                }

                if (MyBSP.backsector.ceilingheight <= MyBSP.frontsector.floorheight) {
                    seg.setSprBottomClip(view.negonearray, 0);
                    seg.bsilheight = Integer.MAX_VALUE;
                    seg.silhouette |= SIL_BOTTOM;
                }

                if (MyBSP.backsector.floorheight >= MyBSP.frontsector.ceilingheight) {
                    seg.setSprTopClip(view.screenheightarray, 0);
                    seg.tsilheight = Integer.MIN_VALUE;
                    seg.silhouette |= SIL_TOP;
                }

                worldhigh = MyBSP.backsector.ceilingheight - view.z;
                worldlow = MyBSP.backsector.floorheight - view.z;

                // hack to allow height changes in outdoor areas
                if (MyBSP.frontsector.ceilingpic == TexMan.getSkyFlatNum()
                        && MyBSP.backsector.ceilingpic == TexMan
                                .getSkyFlatNum()) {
                    worldtop = worldhigh;
                }

                if (worldlow != worldbottom
                        || MyBSP.backsector.floorpic != MyBSP.frontsector.floorpic
                        || MyBSP.backsector.lightlevel != MyBSP.frontsector.lightlevel) {
                    markfloor = true;
                } else {
                    // same plane on both sides
                    markfloor = false;
                }

                if (worldhigh != worldtop
                        || MyBSP.backsector.ceilingpic != MyBSP.frontsector.ceilingpic
                        || MyBSP.backsector.lightlevel != MyBSP.frontsector.lightlevel) {
                    markceiling = true;
                } else {
                    // same plane on both sides
                    markceiling = false;
                }

                if (MyBSP.backsector.ceilingheight <= MyBSP.frontsector.floorheight
                        || MyBSP.backsector.floorheight >= MyBSP.frontsector.ceilingheight) {
                    // closed door
                    markceiling = markfloor = true;
                }

                if (worldhigh < worldtop) {
                    // top texture
                    toptexture =
                        TexMan.getTextureTranslation(MyBSP.sidedef.toptexture);
                    if ((MyBSP.linedef.flags & ML_DONTPEGTOP) != 0) {
                        // top of texture at top
                        rw_toptexturemid = worldtop;
                    } else {
                        vtop =
                            MyBSP.backsector.ceilingheight
                                    + TexMan.getTextureheight(MyBSP.sidedef.toptexture);

                        // bottom of texture
                        rw_toptexturemid = vtop - view.z;
                    }
                }
                if (worldlow > worldbottom) {
                    // bottom texture
                    bottomtexture =
                        TexMan.getTextureTranslation(MyBSP.sidedef.bottomtexture);

                    if ((MyBSP.linedef.flags & ML_DONTPEGBOTTOM) != 0) {
                        // bottom of texture at bottom
                        // top of texture at top
                        rw_bottomtexturemid = worldtop;
                    } else
                        // top of texture at top
                        rw_bottomtexturemid = worldlow;
                }
                rw_toptexturemid += MyBSP.sidedef.rowoffset;
                rw_bottomtexturemid += MyBSP.sidedef.rowoffset;

                // allocate space for masked texture tables
                if (MyBSP.sidedef.midtexture != 0) {
                    // masked midtexture
                    maskedtexture = true;
                    seg_vars.maskedtexturecol = vp_vars.openings;
                    seg_vars.pmaskedtexturecol = vp_vars.lastopening - rw_x;
                    seg.setMaskedTextureCol(seg_vars.maskedtexturecol,
                        seg_vars.pmaskedtexturecol);
                    vp_vars.lastopening += rw_stopx - rw_x;
                }
            }

            // calculate rw_offset (only needed for textured lines)
            segtextured =
                (((midtexture | toptexture | bottomtexture) != 0) | maskedtexture);

            if (segtextured) {
                offsetangle = addAngles(rw_normalangle, -rw_angle1);

                // Another "tricky spot": negative of an unsigned number?
                if (offsetangle > ANG180)
                    offsetangle = (-(int) offsetangle) & BITS32;

                if (offsetangle > ANG90)
                    offsetangle = ANG90;

                sineval = finesine(offsetangle);
                rw_offset = FixedMul(hyp, sineval);

                // Another bug: we CAN'T assume that the result won't wrap
                // around.
                // If that assumption is made, then texture alignment issues
                // appear
                if (((rw_normalangle - rw_angle1) & BITS32) < ANG180)
                    rw_offset = -rw_offset;

                rw_offset += MyBSP.sidedef.textureoffset + MyBSP.curline.offset;
                // This is OK, however: we can add as much shit as we want,
                // as long as we trim it to the 32 LSB. Proof as to why
                // this is always true is left as an exercise to the reader.
                rw_centerangle = (ANG90 + view.angle - rw_normalangle) & BITS32;

                // calculate light table
                // use different light tables
                // for horizontal / vertical / diagonal
                // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
                if (colormaps.fixedcolormap == null) {
                    lightnum =
                        (MyBSP.frontsector.lightlevel >> LIGHTSEGSHIFT)
                                + colormaps.extralight;

                    if (MyBSP.curline.v1y == MyBSP.curline.v2y)
                        lightnum--;
                    else if (MyBSP.curline.v1x == MyBSP.curline.v2x)
                        lightnum++;

                    if (lightnum < 0)
                        colormaps.walllights = colormaps.scalelight[0];
                    else if (lightnum >= LIGHTLEVELS)
                        colormaps.walllights =
                            colormaps.scalelight[LIGHTLEVELS - 1];
                    else
                        colormaps.walllights = colormaps.scalelight[lightnum];
                }
            }

            // if a floor / ceiling plane is on the wrong side
            // of the view plane, it is definitely invisible
            // and doesn't need to be marked.

            if (MyBSP.frontsector.floorheight >= view.z) {
                // above view plane
                markfloor = false;
            }

            if (MyBSP.frontsector.ceilingheight <= view.z
                    && MyBSP.frontsector.ceilingpic != TexMan.getSkyFlatNum()) {
                // below view plane
                markceiling = false;
            }

            // calculate incremental stepping values for texture edges
            worldtop >>= 4;
            worldbottom >>= 4;

            topstep = -FixedMul(rw_scalestep, worldtop);
            topfrac = (view.centeryfrac >> 4) - FixedMul(worldtop, rw_scale);

            bottomstep = -FixedMul(rw_scalestep, worldbottom);
            bottomfrac =
                (view.centeryfrac >> 4) - FixedMul(worldbottom, rw_scale);

            if (MyBSP.backsector != null) {
                worldhigh >>= 4;
                worldlow >>= 4;

                if (worldhigh < worldtop) {
                    pixhigh =
                        (view.centeryfrac >> 4) - FixedMul(worldhigh, rw_scale);
                    pixhighstep = -FixedMul(rw_scalestep, worldhigh);
                }

                if (worldlow > worldbottom) {
                    pixlow =
                        (view.centeryfrac >> 4) - FixedMul(worldlow, rw_scale);
                    pixlowstep = -FixedMul(rw_scalestep, worldlow);
                }
            }

            // render it
            if (markceiling) {
                // System.out.println("Markceiling");
                vp_vars.ceilingplane =
                    vp_vars.CheckPlane(vp_vars.ceilingplane, rw_x, rw_stopx - 1);
            }

            if (markfloor) {
                // System.out.println("Markfloor");
                vp_vars.floorplane =
                    vp_vars.CheckPlane(vp_vars.floorplane, rw_x, rw_stopx - 1);
            }

            RenderSegLoop();

            // After rendering is actually performed, clipping is set.

            // save sprite clipping info ... no top clipping?
            if ((C2JUtils.flags(seg.silhouette, SIL_TOP) || maskedtexture)
                    && seg.nullSprTopClip()) {

                // memcpy (lastopening, ceilingclip+start, 2*(rw_stopx-start));
                System.arraycopy(ceilingclip, start, vp_vars.openings,
                    vp_vars.lastopening, rw_stopx - start);

                seg.setSprTopClip(vp_vars.openings, vp_vars.lastopening - start);
                // seg.setSprTopClipPointer();
                vp_vars.lastopening += rw_stopx - start;
            }
            // no floor clipping?
            if ((C2JUtils.flags(seg.silhouette, SIL_BOTTOM) || maskedtexture)
                    && seg.nullSprBottomClip()) {
                // memcpy (lastopening, floorclip+start, 2*(rw_stopx-start));
                System.arraycopy(floorclip, start, vp_vars.openings,
                    vp_vars.lastopening, rw_stopx - start);
                seg.setSprBottomClip(vp_vars.openings, vp_vars.lastopening
                        - start);
                vp_vars.lastopening += rw_stopx - start;
            }

            if (maskedtexture && C2JUtils.flags(seg.silhouette, SIL_TOP)) {
                seg.silhouette |= SIL_TOP;
                seg.tsilheight = Integer.MIN_VALUE;
            }
            if (maskedtexture && (seg.silhouette & SIL_BOTTOM) == 0) {
                seg.silhouette |= SIL_BOTTOM;
                seg.bsilheight = Integer.MAX_VALUE;
            }
            seg_vars.ds_p++;
        }

        /**
         * R_RenderSegLoop Draws zero, one, or two textures (and possibly a
         * masked texture) for walls. Can draw or mark the starting pixel of
         * floor and ceiling textures. Also sets the actual sprite clipping info
         * (where sprites should be cut) Since rw_x ranges are non-overlapping,
         * rendering all walls means completing the clipping list as well. The
         * only difference between the parallel and the non-parallel version is
         * that the parallel doesn't draw immediately but rather, generates
         * RWIs. This can surely be unified to avoid replicating code. CALLED:
         * CORE LOOPING ROUTINE.
         */

        protected void RenderSegLoop() {
            int angle; // angle_t
            int index;
            int yl; // low
            int yh; // hight
            int mid;
            int texturecolumn = 0; // fixed_t
            int top;
            int bottom;

            for (; rw_x < rw_stopx; rw_x++) {
                // mark floor / ceiling areas
                yl = (topfrac + HEIGHTUNIT - 1) >> HEIGHTBITS;

                // no space above wall?
                if (yl < ceilingclip[rw_x] + 1)
                    yl = ceilingclip[rw_x] + 1;

                if (markceiling) {
                    top = ceilingclip[rw_x] + 1;
                    bottom = yl - 1;

                    if (bottom >= floorclip[rw_x])
                        bottom = floorclip[rw_x] - 1;

                    if (top <= bottom) {
                        vp_vars.visplanes[vp_vars.ceilingplane].setTop(rw_x,
                            (char) top);
                        vp_vars.visplanes[vp_vars.ceilingplane].setBottom(rw_x,
                            (char) bottom);
                    }
                }

                yh = bottomfrac >> HEIGHTBITS;

                if (yh >= floorclip[rw_x])
                    yh = floorclip[rw_x] - 1;

                // A particular seg has been identified as a floor marker.

                if (markfloor) {
                    top = yh + 1;
                    bottom = floorclip[rw_x] - 1;
                    if (top <= ceilingclip[rw_x])
                        top = ceilingclip[rw_x] + 1;
                    if (top <= bottom) {
                        vp_vars.visplanes[vp_vars.floorplane].setTop(rw_x,
                            (char) top);
                        vp_vars.visplanes[vp_vars.floorplane].setBottom(rw_x,
                            (char) bottom);
                    }
                }

                // texturecolumn and lighting are independent of wall tiers
                if (segtextured) {
                    // calculate texture offset

                    // CAREFUL: a VERY anomalous point in the code. Their sum is
                    // supposed
                    // to give an angle not exceeding 45 degrees (or an index of
                    // 0x0FFF after
                    // shifting). If added with pure unsigned rules, this
                    // doesn't hold anymore,
                    // not even if accounting for overflow.
                    angle =
                        Tables.toBAMIndex(rw_centerangle
                                + (int) xtoviewangle[rw_x]);

                    // FIXME: We are accessing finetangent here, the code seems
                    // pretty confident in that angle won't exceed 4K no matter
                    // what.
                    // But xtoviewangle alone can yield 8K when shifted.
                    // This usually only overflows if we idclip and look at
                    // certain directions (probably angles get fucked up),
                    // however it seems rare
                    // enough to just "swallow" the exception. You can eliminate
                    // it by anding
                    // with 0x1FFF if you're so inclined.
                    // FIXED by allowing overflow. See Tables for details.

                    texturecolumn =
                        rw_offset - FixedMul(finetangent[angle], rw_distance);
                    texturecolumn >>= FRACBITS;
                    // calculate lighting
                    index = rw_scale >> LIGHTSCALESHIFT;

                    if (index >= MAXLIGHTSCALE)
                        index = MAXLIGHTSCALE - 1;

                    dcvars.dc_colormap = colormaps.walllights[index];
                    dcvars.dc_x = rw_x;
                    dcvars.dc_iscale = (int) (0xffffffffL / rw_scale);
                }

                // draw the wall tiers
                if (midtexture != 0) {
                    // single sided line
                    dcvars.dc_yl = yl;
                    dcvars.dc_yh = yh;
                    dcvars.dc_texheight =
                        TexMan.getTextureheight(midtexture) >> FRACBITS; // killough
                    dcvars.dc_texturemid = rw_midtexturemid;
                    dcvars.dc_source_ofs = 0;
                    dcvars.dc_source =
                        TexMan.GetCachedColumn(midtexture, texturecolumn);
                    CompleteColumn();
                    ceilingclip[rw_x] = (short) view.height;
                    floorclip[rw_x] = -1;
                } else {
                    // two sided line
                    if (toptexture != 0) {
                        // top wall
                        mid = pixhigh >> HEIGHTBITS;
                        pixhigh += pixhighstep;

                        if (mid >= floorclip[rw_x])
                            mid = floorclip[rw_x] - 1;

                        if (mid >= yl) {
                            dcvars.dc_yl = yl;
                            dcvars.dc_yh = mid;
                            dcvars.dc_texturemid = rw_toptexturemid;
                            dcvars.dc_texheight =
                                TexMan.getTextureheight(toptexture) >> FRACBITS;
                            dcvars.dc_source =
                                (T) TexMan.GetCachedColumn(toptexture,
                                    texturecolumn);
                            dcvars.dc_source_ofs = 0;
                            if (dcvars.dc_colormap == null)
                                System.out.println("Two-sided");
                            CompleteColumn();
                            ceilingclip[rw_x] = (short) mid;
                        } else
                            ceilingclip[rw_x] = (short) (yl - 1);
                    } else {
                        // no top wall
                        if (markceiling)
                            ceilingclip[rw_x] = (short) (yl - 1);
                    }

                    if (bottomtexture != 0) {
                        // bottom wall
                        mid = (pixlow + HEIGHTUNIT - 1) >> HEIGHTBITS;
                        pixlow += pixlowstep;

                        // no space above wall?
                        if (mid <= ceilingclip[rw_x])
                            mid = ceilingclip[rw_x] + 1;

                        if (mid <= yh) {
                            dcvars.dc_yl = mid;
                            dcvars.dc_yh = yh;
                            dcvars.dc_texturemid = rw_bottomtexturemid;
                            dcvars.dc_texheight =
                                TexMan.getTextureheight(bottomtexture) >> FRACBITS;
                            dcvars.dc_source =
                                (T) TexMan.GetCachedColumn(bottomtexture,
                                    texturecolumn);
                            dcvars.dc_source_ofs = 0;
                            CompleteColumn();

                            floorclip[rw_x] = (short) mid;
                        } else
                            floorclip[rw_x] = (short) (yh + 1);
                    } else {
                        // no bottom wall
                        if (markfloor)
                            floorclip[rw_x] = (short) (yh + 1);
                    }

                    if (maskedtexture) {
                        // save texturecol
                        // for backdrawing of masked mid texture
                        seg_vars.maskedtexturecol[seg_vars.pmaskedtexturecol
                                + rw_x] = (short) texturecolumn;
                    }
                }

                rw_scale += rw_scalestep;
                topfrac += topstep;
                bottomfrac += bottomstep;
            }
        }

        @Override
        public void ClearClips() {
            System.arraycopy(BLANKFLOORCLIP, 0, floorclip, 0, view.width);
            System.arraycopy(BLANKCEILINGCLIP, 0, ceilingclip, 0, view.width);
        }

        /**
         * Called from RenderSegLoop. This should either invoke the column
         * function, or store a wall rendering instruction in the parallel
         * version. It's the only difference between the parallel and serial
         * renderer, BTW. So override and implement accordingly.
         */
        protected abstract void CompleteColumn();

        @Override
        public void ExecuteSetViewSize(int viewwidth) {
            for (int i = 0; i < viewwidth; i++) {
                BLANKFLOORCLIP[i] = (short) view.height;
                BLANKCEILINGCLIP[i] = -1;
            }
        }
        
        public void CompleteRendering(){
            // Nothing to do for serial. 
        }

        protected column_t col;

        public SegDrawer(Renderer<?, ?> R) {
            this.vp_vars = R.getVPVars();
            this.seg_vars = R.getSegVars();
            col = new column_t();
            seg_vars.drawsegs = new drawseg_t[seg_vars.MAXDRAWSEGS];
            C2JUtils.initArrayOfObjects(seg_vars.drawsegs);
        }

        /**
         * R_ScaleFromGlobalAngle Returns the texture mapping scale for the
         * current line (horizontal span) at the given angle. rw_distance must
         * be calculated first.
         */

        protected final int ScaleFromGlobalAngle(long visangle) {
            int scale; // fixed_t
            long anglea;
            long angleb;
            int sinea;
            int sineb;
            int num; // fixed_t
            int den;

            // UNUSED
            /*
             * { fixed_t dist; fixed_t z; fixed_t sinv; fixed_t cosv; sinv =
             * finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT]; dist =
             * FixedDiv (rw_distance, sinv); cosv =
             * finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT]; z =
             * abs(FixedMul (dist, cosv)); scale = FixedDiv(projection, z);
             * return scale; }
             */

            anglea = (ANG90 + visangle - view.angle) & BITS32;
            angleb = (ANG90 + visangle - rw_normalangle) & BITS32;

            // both sines are allways positive
            sinea = finesine(anglea);
            sineb = finesine(angleb);
            num = FixedMul(view.projection, sineb) << view.detailshift;
            den = FixedMul(rw_distance, sinea);

            if (den > num >> 16) {
                scale = FixedDiv(num, den);

                if (scale > 64 * FRACUNIT)
                    scale = 64 * FRACUNIT;
                else if (scale < 256)
                    scale = 256;
            } else
                scale = 64 * FRACUNIT;

            return scale;
        }

        public void setGlobalAngle(long angle) {
            this.rw_angle1 = angle;
        }
        
        public void initScaling() {
            this.floorclip = new short[vs.getScreenWidth()];
            this.ceilingclip = new short[vs.getScreenWidth()];
            BLANKFLOORCLIP = new short[vs.getScreenWidth()];
            BLANKCEILINGCLIP = new short[vs.getScreenWidth()];
        }

        @Override
        public void setVideoScale(IVideoScale vs) {
            this.vs = vs;
        }

        IVideoScale vs;
    }

    protected interface IPlaneDrawer
            extends IVideoScaleAware {

        void InitPlanes();

        void MapPlane(int y, int x1, int x2);

        void DrawPlanes();

        int[] getDistScale();
        
        /** Sync up in case there's concurrent planes/walls rendering */
        public void sync();

    }

    protected interface ISegDrawer
            extends IVideoScaleAware, ILimitResettable {
        public void ClearClips();

        short[] getBLANKCEILINGCLIP();

        short[] getBLANKFLOORCLIP();

        short[] getFloorClip();

        short[] getCeilingClip();

        void ExecuteSetViewSize(int viewwidth);

        public void setGlobalAngle(long angle1);

        public void StoreWallRange(int first, int last);

        /** If there is anything to do beyond the BPS traversal,
         * e.g. parallel rendering
         */
        public void CompleteRendering();

        /** Sync up in case there's concurrent planes/walls rendering */
        public void sync();
    }

    protected final class Planes
            extends PlaneDrawer<T, V> {

        public Planes(RendererState<T, V> R) {
            super(R);
        }

        /**
         * R_DrawPlanes At the end of each frame. This also means that visplanes
         * must have been set BEFORE we called this function. Therefore, look
         * for errors behind.
         * 
         * @throws IOException
         */

        @Override
        public final void DrawPlanes() {
            if (DEBUG)
                System.out.println(" >>>>>>>>>>>>>>>>>>>>>   DrawPlanes: "
                        + vp_vars.lastvisplane);
            visplane_t pln = null; // visplane_t
            int light;
            int x;
            int stop;
            int angle;

            if (RANGECHECK) {
                rangeCheckErrors();
            }

            for (int pl = 0; pl < vp_vars.lastvisplane; pl++) {
                pln = vp_vars.visplanes[pl];
                if (DEBUG2)
                    System.out.println(pln);

                if (pln.minx > pln.maxx)
                    continue;
                // sky flat
                if (pln.picnum == TexMan.getSkyFlatNum()) {
                    // Cache skytexture stuff here. They aren't going to change
                    // while
                    // being drawn, after all, are they?
                    int skytexture = TexMan.getSkyTexture();
                    skydcvars.dc_texheight =
                        TexMan.getTextureheight(skytexture) >> FRACBITS;
                    skydcvars.dc_iscale =
                        vpvars.getSkyScale() >> view.detailshift;

                    /*
                     * Sky is allways drawn full bright, i.e. colormaps[0] is
                     * used. Because of this hack, sky is not affected by INVUL
                     * inverse mapping.
                     */
                    skydcvars.dc_colormap = colormap.colormaps[0];
                    skydcvars.dc_texturemid = TexMan.getSkyTextureMid();
                    for (x = pln.minx; x <= pln.maxx; x++) {

                        skydcvars.dc_yl = pln.getTop(x);
                        skydcvars.dc_yh = pln.getBottom(x);

                        if (skydcvars.dc_yl <= skydcvars.dc_yh) {
                            angle =
                                (int) (addAngles(view.angle, xtoviewangle[x]) >>> ANGLETOSKYSHIFT);
                            skydcvars.dc_x = x;
                            // Optimized: texheight is going to be the same
                            // during normal skies drawing...right?
                            skydcvars.dc_source =
                                TexMan.GetCachedColumn(skytexture, angle);
                            colfunc.sky.invoke();
                        }
                    }
                    continue;
                }

                // regular flat
                dsvars.ds_source = TexMan.getSafeFlat(pln.picnum);

                planeheight = Math.abs(pln.height - view.z);
                light = (pln.lightlevel >> LIGHTSEGSHIFT) + colormap.extralight;

                if (light >= LIGHTLEVELS)
                    light = LIGHTLEVELS - 1;

                if (light < 0)
                    light = 0;

                planezlight = colormap.zlight[light];

                // We set those values at the border of a plane's top to a
                // "sentinel" value...ok.
                pln.setTop(pln.maxx + 1, visplane_t.SENTINEL);
                pln.setTop(pln.minx - 1, visplane_t.SENTINEL);

                stop = pln.maxx + 1;

                for (x = pln.minx; x <= stop; x++) {
                    MakeSpans(x, pln.getTop(x - 1), pln.getBottom(x - 1),
                        pln.getTop(x), pln.getBottom(x));
                }

                // Z_ChangeTag (ds_source, PU_CACHE);
            }
        }

    } // End Plane class

    // /////////////////////// LIGHTS, POINTERS, COLORMAPS ETC. ////////////////

    // /// FROM R_DATA, R_MAIN , R_DRAW //////////

    /**
     * OK< this is supposed to "peg" into screen buffer 0. It will work AS LONG
     * AS SOMEONE FUCKING ACTUALLY SETS IT !!!!
     */
    protected V screen;

    protected static final boolean RANGECHECK = false;

    /**
     * These are actually offsets inside screen 0 (or any screen). Therefore
     * anything using them should "draw" inside screen 0
     */
    protected int[] ylookup = new int[MAXHEIGHT];

    /** Columns offset to set where?! */
    protected int[] columnofs = new int[MAXWIDTH];

    /**
     * General purpose. Used for solid walls and as an intermediary for
     * threading
     */

    protected ColVars<T, V> dcvars;

    /** Used for spans */

    protected SpanVars<T, V> dsvars;

    // Used for sky drawer, to avoid clashing with shared dcvars
    protected ColVars<T, V> skydcvars;

    /**
     * Masked drawing functions get "pegged" to this set of dcvars, passed upon
     * initialization. However, multi-threaded vars are better off carrying each
     * their own ones.
     */
    protected ColVars<T, V> maskedcvars;

    /**
     * e6y: wide-res Borrowed from PrBoom+;
     */

    /*
     * protected int wide_centerx, wide_ratio, wide_offsetx, wide_offset2x,
     * wide_offsety, wide_offset2y; protected final base_ratio_t[]
     * BaseRatioSizes = { new base_ratio_t(960, 600, 0, 48, 1.333333f), // 4:3
     * new base_ratio_t(1280, 450, 0, 48 * 3 / 4, 1.777777f), // 16:9 new
     * base_ratio_t(1152, 500, 0, 48 * 5 / 6, 1.6f), // 16:10 new
     * base_ratio_t(960, 600, 0, 48, 1.333333f), new base_ratio_t(960, 640,
     * (int) (6.5 * FRACUNIT), 48 * 15 / 16, 1.25f) // 5:4 };
     */

    /** just for profiling purposes */
    protected int framecount;

    protected int sscount;

    protected int linecount;

    protected int loopcount;

    //
    // precalculated math tables
    //
    protected long clipangle;

    // Set to 2*clipangle later.
    protected long CLIPANGLE2;

    // The viewangletox[viewangle + FINEANGLES/4] lookup
    // maps the visible view angles to screen X coordinates,
    // flattening the arc to a flat projection plane.
    // There will be many angles mapped to the same X.

    protected final int[] viewangletox = new int[FINEANGLES / 2];

    /**
     * The xtoviewangle[] table maps a screen pixel to the lowest viewangle that
     * maps back to x ranges from clipangle to -clipangle.
     */
    protected long[] xtoviewangle;// MAES: to resize

    // UNUSED.
    // The finetangentgent[angle+FINEANGLES/4] table
    // holds the fixed_t tangent values for view angles,
    // ranging from MININT to 0 to MAXINT.
    // fixed_t finetangent[FINEANGLES/2];

    // fixed_t finesine[5*FINEANGLES/4];
    // MAES: uh oh. So now all these ints must become finesines? fuck that.
    // Also wtf @ this hack....this points to approx 1/4th of the finesine
    // table, but what happens if I read past it?
    // int[] finecosine = finesine[FINEANGLES/4];

    /*
     * MAES: what's going on with light tables here. OK...so these should be
     * "unsigned bytes", since, after all, they'll be used as pointers inside an
     * array to finally pick a color, so they should be expanded to shorts.
     */

    // //////////// SOME UTILITY METHODS /////////////

    /**
     * Assigns a point of view before calling PointToAngle CAREFUL: this isn't a
     * pure function, as it alters the renderer's state!
     */

    public final long PointToAngle2(int x1, int y1, int x2, int y2) {
        // Careful with assignments...
        view.x = x1;
        view.y = y1;

        return view.PointToAngle(x2, y2);
    }

    //
    // R_InitPointToAngle
    //
    /*
     * protected final void InitPointToAngle () { // UNUSED - now getting from
     * tables.c if (false){ int i; long t; float f; // // slope (tangent) to
     * angle lookup // for (i=0 ; i<=SLOPERANGE ; i++) { f = (float) Math.atan(
     * (double)(i/SLOPERANGE )/(3.141592657*2)); t = (long) (0xffffffffL*f);
     * tantoangle[i] = (int) t; } } }
     */

    /**
     * Public, static, stateless version of PointToAngle2. Call this one when
     * "renderless" use of PointToAngle2 is required.
     */

    public final static long PointToAngle(int viewx, int viewy, int x, int y) {
        // MAES: note how we don't use &BITS32 here. That is because
        // we know that the maximum possible value of tantoangle is angle
        // This way, we are actually working with vectors emanating
        // from our current position.
        x -= viewx;
        y -= viewy;

        if ((x == 0) && (y == 0))
            return 0;

        if (x >= 0) {
            // x >=0
            if (y >= 0) {
                // y>= 0

                if (x > y) {
                    // octant 0
                    return tantoangle[SlopeDiv(y, x)];
                } else {
                    // octant 1
                    return (ANG90 - 1 - tantoangle[SlopeDiv(x, y)]);
                }
            } else {
                // y<0
                y = -y;

                if (x > y) {
                    // octant 8
                    return (-tantoangle[SlopeDiv(y, x)]);
                } else {
                    // octant 7
                    return (ANG270 + tantoangle[SlopeDiv(x, y)]);
                }
            }
        } else {
            // x<0
            x = -x;

            if (y >= 0) {
                // y>= 0
                if (x > y) {
                    // octant 3
                    return (ANG180 - 1 - tantoangle[SlopeDiv(y, x)]);
                } else {
                    // octant 2
                    return (ANG90 + tantoangle[SlopeDiv(x, y)]);
                }
            } else {
                // y<0
                y = -y;

                if (x > y) {
                    // octant 4
                    return (ANG180 + tantoangle[SlopeDiv(y, x)]);
                } else {
                    // octant 5
                    return (ANG270 - 1 - tantoangle[SlopeDiv(x, y)]);
                }
            }
        }
        // This is actually unreachable.
        // return 0;
    }

    //
    // R_InitTables
    //
    protected final void InitTables() {
        // UNUSED: now getting from tables.c
        /*
         * int i; float a; float fv; int t; // viewangle tangent table for (i=0
         * ; i<FINEANGLES/2 ; i++) { a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES;
         * fv = FRACUNIT*tan (a); t = fv; finetangent[i] = t; } // finesine
         * table for (i=0 ; i<5*FINEANGLES/4 ; i++) { // OPTIMIZE: mirro.. a =
         * (i+0.5)*PI*2/FINEANGLES; t = FRACUNIT*sin (a); finesine[i] = t; }
         */

    }

    /**
     * R_PointToDist
     * 
     * @param x
     *        fixed_t
     * @param y
     *        fixed_t
     * @return
     */

    protected final int PointToDist(int x, int y) {
        int angle;
        int dx;
        int dy;
        int temp;
        int dist;

        dx = Math.abs(x - view.x);
        dy = Math.abs(y - view.y);

        // If something is farther north/south than west/east, it gets swapped.
        // Probably as a crude way to avoid divisions by zero. This divides
        // the field into octants, rather than quadrants, where the biggest
        // angle to
        // consider is 45...right? So dy/dx can never exceed 1.0, in theory.

        if (dy > dx) {
            temp = dx;
            dx = dy;
            dy = temp;
        }

        // If one or both of the distances are *exactly* zero at this point,
        // then this means that the wall is in your face anyway, plus we want to
        // avoid a division by zero. So you get zero.
        if (dx == 0)
            return 0;

        /*
         * If dx is zero, this is going to bomb. Fixeddiv will return MAXINT aka
         * 7FFFFFFF, >> DBITS will make it 3FFFFFF, which is more than enough to
         * break tantoangle[]. In the original C code, this probably didn't
         * matter: there would probably be garbage orientations thrown all
         * around. However this is unacceptable in Java. OK, so the safeguard
         * above prevents that. Still... this method is only called once per
         * visible wall per frame, so one check more or less at this point won't
         * change much. It's better to be safe than sorry.
         */

        // This effectively limits the angle to
        // angle = Math.max(FixedDiv(dy, dx), 2048) >> DBITS;
        angle = (FixedDiv(dy, dx) & 0x1FFFF) >> DBITS;

        // Since the division will be 0xFFFF at most, DBITS will restrict
        // the maximum angle index to 7FF, about 45, so adding ANG90 with
        // no other safeguards is OK.
        angle = (int) ((tantoangle[angle] + ANG90) >> ANGLETOFINESHIFT);

        // use as cosine
        dist = FixedDiv(dx, finesine[angle]);

        return dist;
    }

    // //////////// COMMON RENDERING GLOBALS ////////////////

    // //////////////// COLUMN AND SPAN FUNCTIONS //////////////

    protected ColFuncs<T, V> colfunc;

    // Keep two sets of functions.
    protected ColFuncs<T, V> colfunchi;

    protected ColFuncs<T, V> colfunclow;

    protected final void setHiColFuns() {
        colfunchi.main = colfunchi.base = DrawColumn;
        colfunchi.masked = DrawColumnMasked;
        colfunchi.fuzz = DrawFuzzColumn;
        colfunchi.trans = DrawTranslatedColumn;
        colfunchi.glass = DrawTLColumn;
        colfunchi.player = DrawColumnPlayer;
        colfunchi.sky = DrawColumnSkies;
    }

    protected final void setLowColFuns() {
        colfunclow.main = colfunclow.base = DrawColumnLow;
        colfunclow.masked = DrawColumnMaskedLow;
        colfunclow.fuzz = DrawFuzzColumnLow;
        colfunclow.trans = DrawTranslatedColumnLow;
        colfunclow.glass = DrawTLColumn;
        colfunclow.player = DrawColumnMaskedLow;
        colfunclow.sky = DrawColumnSkiesLow;
    }
    
    public ColFuncs<T,V> getColFuncsHi(){
        return this.colfunchi;
    }
   
    public ColFuncs<T,V> getColFuncsLow(){
        return this.colfunclow;
    }
    
    public ColVars<T, V> getMaskedDCVars(){
        return this.maskedcvars;
    }
    
    
    // These column functions are "fixed" for a given renderer, and are
    // not used directly, but only after passing them to colfuncs

    protected DoomColumnFunction<T, V> DrawTranslatedColumn;

    protected DoomColumnFunction<T, V> DrawTranslatedColumnLow;

    protected DoomColumnFunction<T, V> DrawColumnPlayer;

    protected DoomColumnFunction<T, V> DrawColumnSkies;

    protected DoomColumnFunction<T, V> DrawColumnSkiesLow;

    protected DoomColumnFunction<T, V> DrawFuzzColumn;

    protected DoomColumnFunction<T, V> DrawFuzzColumnLow;

    protected DoomColumnFunction<T, V> DrawColumn;

    protected DoomColumnFunction<T, V> DrawColumnLow;

    protected DoomColumnFunction<T, V> DrawColumnMasked;

    protected DoomColumnFunction<T, V> DrawColumnMaskedLow;

    protected DoomColumnFunction<T, V> DrawTLColumn;

    /** to be set in UnifiedRenderer */
    protected DoomSpanFunction<T, V> DrawSpan, DrawSpanLow;

    // ////////////// r_draw methods //////////////

    /**
     * Copy a screen buffer. Actually, it's hardcoded to copy stuff from screen
     * 1 to screen 0. Used to overlay stuff like beveled edges that don't need
     * to be updated that often. * LFB copy. This might not be a good idea if
     * memcpy is not optiomal, e.g. byte by byte on a 32bit CPU, as GNU
     * GCC/Linux libc did at one point.
     */
    public void VideoErase(int ofs, int count) {

        // memcpy (screens[0]+ofs, screens[1]+ofs, count);
        System.arraycopy(V.getScreen(DoomVideoRenderer.SCREEN_BG), ofs,
            V.getScreen(DoomVideoRenderer.SCREEN_FG), ofs, count);

    }

    /*
     * R_DrawViewBorder Draws the border around the view for different size
     * windows?
     */

    public void DrawViewBorder() {
        int top;
        int side;
        int ofs;
        int i;

        if (view.scaledwidth == SCREENWIDTH)
            return;

        top = ((SCREENHEIGHT - DM.ST.getHeight()) - view.height) / 2;
        side = (SCREENWIDTH - view.scaledwidth) / 2;

        // copy top and one line of left side
        this.VideoErase(0, top * SCREENWIDTH + side);

        // copy one line of right side and bottom
        ofs = (view.height + top) * SCREENWIDTH - side;
        this.VideoErase(ofs, top * SCREENWIDTH + side);

        // copy sides using wraparound
        ofs = top * SCREENWIDTH + SCREENWIDTH - side;
        side <<= 1;

        for (i = 1; i < view.height; i++) {
            this.VideoErase(ofs, side);
            ofs += SCREENWIDTH;
        }

        // ?
        V.MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT - DM.ST.getHeight());
    }

    public void ExecuteSetViewSize() {
        int cosadj;
        int dy;
        int i;
        int j;
        int level;
        int startmap;

        setsizeneeded = false;

        // 11 Blocks means "full screen"

        if (setblocks == 11) {
            view.scaledwidth = SCREENWIDTH;
            view.height = SCREENHEIGHT;
        } else {
            view.scaledwidth = setblocks * (SCREENWIDTH / 10);
            // Height can only be a multiple of 8.
            view.height =
                (short) ((setblocks * (SCREENHEIGHT - DM.ST.getHeight()) / 10) & ~7);
        }

        skydcvars.viewheight =
            maskedcvars.viewheight = dcvars.viewheight = view.height;

        view.detailshift = setdetail;
        view.width = view.scaledwidth >> view.detailshift;

        view.centery = view.height / 2;
        view.centerx = view.width / 2;
        view.centerxfrac = (view.centerx << FRACBITS);
        view.centeryfrac = (view.centery << FRACBITS);
        view.projection = view.centerxfrac;

        skydcvars.centery = maskedcvars.centery = dcvars.centery = view.centery;

        // High detail
        if (view.detailshift == 0) {

            colfunc = colfunchi;
            dsvars.spanfunc = DrawSpan;
        } else {
            // Low detail
            colfunc = colfunclow;
            dsvars.spanfunc = DrawSpanLow;

        }

        InitBuffer(view.scaledwidth, view.height);

        InitTextureMapping();

        // psprite scales
        // pspritescale = FRACUNIT*viewwidth/SCREENWIDTH;
        // pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth;

        MyThings.setPspriteScale((int) (FRACUNIT
                * ((float) SCREEN_MUL * view.width) / SCREENWIDTH));
        MyThings.setPspriteIscale((int) (FRACUNIT * (SCREENWIDTH / (view.width * (float) SCREEN_MUL))));
        vp_vars.setSkyScale((int) (FRACUNIT * (SCREENWIDTH / (view.width * (float) SCREEN_MUL))));

        view.BOBADJUST = (int) (this.vs.getSafeScaling() << 15);
        view.WEAPONADJUST = (int) ((SCREENWIDTH / (2 * SCREEN_MUL)) * FRACUNIT);

        // thing clipping
        for (i = 0; i < view.width; i++)
            view.screenheightarray[i] = (short) view.height;

        // planes
        for (i = 0; i < view.height; i++) {
            dy = ((i - view.height / 2) << FRACBITS) + FRACUNIT / 2;
            dy = Math.abs(dy);
            vp_vars.yslope[i] =
                FixedDiv((view.width << view.detailshift) / 2 * FRACUNIT, dy);
            // MyPlanes.yslopef[i] = ((viewwidth<<detailshift)/2)/ dy;
        }

        // double cosadjf;
        for (i = 0; i < view.width; i++) {
            // MAES: In this spot we must interpet it as SIGNED, else it's
            // pointless, right?
            // MAES: this spot caused the "warped floor bug", now fixed. Don't
            // forget xtoviewangle[i]!
            cosadj = Math.abs(finecosine(xtoviewangle[i]));
            // cosadjf =
            // Math.abs(Math.cos((double)xtoviewangle[i]/(double)0xFFFFFFFFL));
            MyPlanes.getDistScale()[i] = FixedDiv(FRACUNIT, cosadj);
            // MyPlanes.distscalef[i] = (float) (1.0/cosadjf);
        }

        // Calculate the light levels to use
        // for each level / scale combination.
        for (i = 0; i < LIGHTLEVELS; i++) {
            startmap = ((LIGHTLEVELS-LIGHTBRIGHT-i)*2)*NUMCOLORMAPS/LIGHTLEVELS;
            for (j = 0; j < MAXLIGHTSCALE; j++) {
                level =
                    startmap - j/ DISTMAP;
                if (level < 0)
                    level = 0;
                if (level >= NUMCOLORMAPS)
                    level = NUMCOLORMAPS - 1;
                colormaps.scalelight[i][j] = colormaps.colormaps[level];
            }
        }

        MySegs.ExecuteSetViewSize(view.width);

    }

    /**
     * R_FillBackScreen Fills the back screen with a pattern for variable screen
     * sizes Also draws a beveled edge. This is actually stored in screen 1, and
     * is only OCCASIONALLY written to screen 0 (the visible one) by calling
     * R_VideoErase.
     */

    public void FillBackScreen() {
        flat_t src;
        int x;
        int y;
        patch_t patch;

        // DOOM border patch.
        String name1 = "FLOOR7_2";

        // DOOM II border patch.
        String name2 = "GRNROCK";

        String name;

        if (view.scaledwidth == SCREENWIDTH)
            return;

        if (DM.isCommercial())
            name = name2;
        else
            name = name1;

        /* This is a flat we're reading here */
        src = (flat_t) (W.CacheLumpName(name, PU_CACHE, flat_t.class));

        /*
         * This part actually draws the border itself, without bevels MAES:
         * improved drawing routine for extended bit-depth compatibility.
         */

        for (y = 0; y < SCREENHEIGHT - DM.ST.getHeight(); y += 64) {

            int y_maxdraw = Math.min(SCREENHEIGHT - DM.ST.getHeight() - y, 64);

            // Draw whole blocks.
            for (x = 0; x < SCREENWIDTH; x += 64) {
                int x_maxdraw = Math.min(SCREENWIDTH - x, 64);
                V.DrawBlock(x, y, DoomVideoRenderer.SCREEN_BG, x_maxdraw,
                    y_maxdraw, (T) src.data);
            }
        }

        patch = (patch_t) W.CachePatchName("BRDR_T", PU_CACHE);

        for (x = 0; x < view.scaledwidth; x += 8)
            V.DrawPatch(view.windowx + x, view.windowy - 8, 1, patch);
        patch = (patch_t) W.CachePatchName("BRDR_B", PU_CACHE);

        for (x = 0; x < view.scaledwidth; x += 8)
            V.DrawPatch(view.windowx + x, view.windowy + view.height, 1, patch);
        patch = (patch_t) W.CachePatchName("BRDR_L", PU_CACHE);

        for (y = 0; y < view.height; y += 8)
            V.DrawPatch(view.windowx - 8, view.windowy + y, 1, patch);
        patch = (patch_t) W.CachePatchName("BRDR_R", PU_CACHE);

        for (y = 0; y < view.height; y += 8)
            V.DrawPatch(view.windowx + view.scaledwidth, view.windowy + y, 1,
                patch);

        // Draw beveled edge. Top-left
        V.DrawPatch(view.windowx - 8, view.windowy - 8, 1,
            (patch_t) W.CachePatchName("BRDR_TL", PU_CACHE));

        // Top-right.
        V.DrawPatch(view.windowx + view.scaledwidth, view.windowy - 8, 1,
            (patch_t) W.CachePatchName("BRDR_TR", PU_CACHE));

        // Bottom-left
        V.DrawPatch(view.windowx - 8, view.windowy + view.height, 1,
            (patch_t) W.CachePatchName("BRDR_BL", PU_CACHE));
        // Bottom-right.
        V.DrawPatch(view.windowx + view.width, view.windowy + view.height, 1,
            (patch_t) W.CachePatchName("BRDR_BR", PU_CACHE));
    }

    /**
     * R_Init
     */

    public void Init()

    {
        // Any good reason for this to be here?
        // drawsegs=new drawseg_t[MAXDRAWSEGS];
        // C2JUtils.initArrayOfObjects(drawsegs);

        // DON'T FORGET ABOUT MEEEEEE!!!11!!!
        this.screen = this.V.getScreen(DoomVideoRenderer.SCREEN_FG);

        System.out.print("\nR_InitData");
        InitData();
        // InitPointToAngle ();
        System.out.print("\nR_InitPointToAngle");

        // ds.DM.viewwidth / ds.viewheight / detailLevel are set by the defaults
        System.out.print("\nR_InitTables");
        InitTables();

        SetViewSize(DM.M.getScreenBlocks(), DM.M.getDetailLevel());

        System.out.print("\nR_InitPlanes");
        MyPlanes.InitPlanes();

        System.out.print("\nR_InitLightTables");
        InitLightTables();

        System.out.print("\nR_InitSkyMap: " + TexMan.InitSkyMap());

        System.out.print("\nR_InitTranslationsTables");
        InitTranslationTables();

        System.out.print("\nR_InitTranMap: ");
        R_InitTranMap(0);

        System.out.print("\nR_InitDrawingFunctions: ");
        R_InitDrawingFunctions();
        
        framecount = 0;
    }        
    
    /**
     * R_InitBuffer Creates lookup tables that avoid multiplies and other
     * hazzles for getting the framebuffer address of a pixel to draw. MAES:
     * this is "pinned" to screen[0] of a Video Renderer. We will handle this
     * differently elsewhere...
     */

    protected final void InitBuffer(int width, int height) {
        int i;

        // Handle resize,
        // e.g. smaller view windows
        // with border and/or status bar.
        view.windowx = (SCREENWIDTH - width) >> 1;

        // Column offset. For windows.
        for (i = 0; i < width; i++)
            columnofs[i] = view.windowx + i;

        // SamE with base row offset.
        if (width == SCREENWIDTH)
            view.windowy = 0;
        else
            view.windowy = (SCREENHEIGHT - DM.ST.getHeight() - height) >> 1;

        // Preclaculate all row offsets.
        for (i = 0; i < height; i++)
            ylookup[i] = /* screens[0] + */(i + view.windowy) * SCREENWIDTH;
    }

    /**
     * R_InitTextureMapping Not moved into the TextureManager because it's
     * tighly coupled to the visuals, rather than textures. Perhaps the name is
     * not the most appropriate.
     */
    protected final void InitTextureMapping() {
        int i, x, t;
        int focallength; // fixed_t
        int fov = FIELDOFVIEW;

        // For widescreen displays, increase the FOV so that the middle part of
        // the
        // screen that would be visible on a 4:3 display has the requested FOV.
        /*
         * UNUSED if (wide_centerx != centerx) { // wide_centerx is what centerx
         * would be // if the display was not widescreen fov = (int)
         * (Math.atan((double) centerx Math.tan((double) fov * Math.PI /
         * FINEANGLES) / (double) wide_centerx) FINEANGLES / Math.PI); if (fov >
         * 130 * FINEANGLES / 360) fov = 130 * FINEANGLES / 360; }
         */

        // Use tangent table to generate viewangletox:
        // viewangletox will give the next greatest x
        // after the view angle.
        //
        // Calc focallength
        // so FIELDOFVIEW angles covers SCREENWIDTH.
        focallength =
            FixedDiv(view.centerxfrac, finetangent[QUARTERMARK + FIELDOFVIEW
                    / 2]);

        for (i = 0; i < FINEANGLES / 2; i++) {
            if (finetangent[i] > FRACUNIT * 2)
                t = -1;
            else if (finetangent[i] < -FRACUNIT * 2)
                t = view.width + 1;
            else {
                t = FixedMul(finetangent[i], focallength);
                t = (view.centerxfrac - t + FRACUNIT - 1) >> FRACBITS;

                if (t < -1)
                    t = -1;
                else if (t > view.width + 1)
                    t = view.width + 1;
            }
            viewangletox[i] = t;
        }

        // Scan viewangletox[] to generate xtoviewangle[]:
        // xtoviewangle will give the smallest view angle
        // that maps to x.
        for (x = 0; x <= view.width; x++) {
            i = 0;
            while (viewangletox[i] > x)
                i++;
            xtoviewangle[x] = addAngles((i << ANGLETOFINESHIFT), -ANG90);
        }

        // Take out the fencepost cases from viewangletox.
        for (i = 0; i < FINEANGLES / 2; i++) {
            t = FixedMul(finetangent[i], focallength);
            t = view.centerx - t;

            if (viewangletox[i] == -1)
                viewangletox[i] = 0;
            else if (viewangletox[i] == view.width + 1)
                viewangletox[i] = view.width;
        }

        clipangle = xtoviewangle[0];
        // OPTIMIZE: assign constant for optimization.
        CLIPANGLE2 = (2 * clipangle) & BITS32;
    }

    //
    // R_InitLightTables
    // Only inits the zlight table,
    // because the scalelight table changes with view size.
    //
    protected final static int DISTMAP = 2;

    protected final void InitLightTables() {
        int i;
        int j;
        int startmap;
        int scale;

        // Calculate the light levels to use
        // for each level / distance combination.
        for (i = 0; i < LIGHTLEVELS; i++) {
            startmap = ((LIGHTLEVELS - LIGHTBRIGHT - i) * 2) * NUMCOLORMAPS / LIGHTLEVELS;
            for (j = 0; j < MAXLIGHTZ; j++) {
                // CPhipps - use 320 here instead of SCREENWIDTH, otherwise hires is
                //           brighter than normal res
                
                scale = FixedDiv((320 / 2 * FRACUNIT), (j + 1) << LIGHTZSHIFT);
                int t, level = startmap - (scale >>= LIGHTSCALESHIFT)/DISTMAP;

                if (level < 0)
                    level = 0;

                if (level >= NUMCOLORMAPS)
                    level = NUMCOLORMAPS - 1;

                // zlight[i][j] = colormaps + level*256;
                colormaps.zlight[i][j] = colormaps.colormaps[level];
            }
        }
    }

    protected static final int TSC = 12; /*
                                          * number of fixed point digits in
                                          * filter percent
                                          */

    byte[] main_tranmap;

    /**
     * A faster implementation of the tranmap calculations. Almost 10x faster
     * than the old one!
     * 
     * @param progress
     */

    protected void R_InitTranMap(int progress) {
        int lump = W.CheckNumForName("TRANMAP");

        long ta = System.nanoTime();
        int p;
        String tranmap;

        // PRIORITY: a map file has been specified from commandline. Try to read
        // it. If OK, this trumps even those specified in lumps.

        if ((p = DM.CM.CheckParm("-tranmap")) != 0) {
            if ((tranmap = DM.CM.getArgv(p + 1)) != null) {
                if (C2JUtils.testReadAccess(tranmap)) {
                    System.out
                            .printf(
                                "Translucency map file %s specified in -tranmap arg. Attempting to use...\n",
                                tranmap);
                    main_tranmap = new byte[256 * 256]; // killough 4/11/98
                    int result = MenuMisc.ReadFile(tranmap, main_tranmap);
                    if (result > 0)
                        return;
                    System.out.print("...failure.\n");
                }
            }
        }

        // Next, if a tranlucency filter map lump is present, use it
        if (lump != -1) { // Set a pointer to the translucency filter maps.
            System.out
                    .print("Translucency map found in lump. Attempting to use...");
            // main_tranmap=new byte[256*256]; // killough 4/11/98
            main_tranmap = W.CacheLumpNumAsRawBytes(lump, Defines.PU_STATIC); // killough
                                                                              // 4/11/98
            // Tolerate 64K or more.
            if (main_tranmap.length >= 0x10000)
                return;
            System.out.print("...failure.\n"); // Not good, try something else.
        }

        // A default map file already exists. Try to read it.
        if (C2JUtils.testReadAccess("tranmap.dat")) {
            System.out
                    .print("Translucency map found in default tranmap.dat file. Attempting to use...");
            main_tranmap = new byte[256 * 256]; // killough 4/11/98
            int result = MenuMisc.ReadFile("tranmap.dat", main_tranmap);
            if (result > 0)
                return; // Something went wrong, so fuck that.
        }

        // Nothing to do, so we must synthesize it from scratch. And, boy, is it
        // slooow.
        { // Compose a default transparent filter map based on PLAYPAL.
            System.out
                    .print("Computing translucency map from scratch...that's gonna be SLOW...");
            byte[] playpal =
                W.CacheLumpNameAsRawBytes("PLAYPAL", Defines.PU_STATIC);
            main_tranmap = new byte[256 * 256]; // killough 4/11/98
            int[] basepal = new int[3 * 256];
            int[] mixedpal = new int[3 * 256 * 256];

            main_tranmap = new byte[256 * 256];

            // Init array of base colors.
            for (int i = 0; i < 256; i++) {
                basepal[3 * i] = 0Xff & playpal[i * 3];
                basepal[1 + 3 * i] = 0Xff & playpal[1 + i * 3];
                basepal[2 + 3 * i] = 0Xff & playpal[2 + i * 3];
            }

            // Init array of mixed colors. These are true RGB.
            // The diagonal of this array will be the original colors.

            for (int i = 0; i < 256 * 3; i += 3) {
                for (int j = 0; j < 256 * 3; j += 3) {
                    mixColors(basepal, basepal, mixedpal, i, j, j * 256 + i);

                }
            }

            // Init distance map. Every original palette colour has a
            // certain distance from all the others. The diagonal is zero.
            // The interpretation is that e.g. the mixture of color 2 and 8 will
            // have a RGB value, which is closest to euclidean distance to
            // e.g. original color 9. Therefore we should put "9" in the (2,8)
            // and (8,2) cells of the tranmap.

            final float[] tmpdist = new float[256];

            for (int a = 0; a < 256; a++) {
                for (int b = a; b < 256; b++) {
                    // We evaluate the mixture of a and b
                    // Construct distance table vs all of the ORIGINAL colors.
                    for (int k = 0; k < 256; k++) {
                        tmpdist[k] =
                            colorDistance(mixedpal, basepal, 3 * (a + b * 256),
                                k * 3);
                    }

                    main_tranmap[(a << 8) | b] = (byte) findMin(tmpdist);
                    main_tranmap[(b << 8) | a] = main_tranmap[(a << 8) | b];
                }
            }
            System.out.print("...done\n");
            if (MenuMisc.WriteFile("tranmap.dat", main_tranmap,
                main_tranmap.length))
                System.out
                        .print("TRANMAP.DAT saved to disk for your convenience! Next time will be faster.\n");
        }
        long b = System.nanoTime();

        System.out.printf("Tranmap %d\n", (b - ta) / 1000000);
    }

    /** Mixes two RGB colors. Nuff said */

    protected final void mixColors(int[] a, int[] b, int[] c, int pa, int pb,
            int pc) {
        c[pc] = (a[pa] + b[pb]) / 2;
        c[pc + 1] = (a[pa + 1] + b[pb + 1]) / 2;
        c[pc + 2] = (a[pa + 2] + b[pb + 2]) / 2;

    }

    /** Returns the euclidean distance of two RGB colors. Nuff said */

    protected final float colorDistance(int[] a, int[] b, int pa, int pb) {
        return (float) Math.sqrt((a[pa] - b[pb]) * (a[pa] - b[pb])
                + (a[pa + 1] - b[pb + 1]) * (a[pa + 1] - b[pb + 1])
                + (a[pa + 2] - b[pb + 2]) * (a[pa + 2] - b[pb + 2]));
    }

    
    /** Stuff that is trivially initializable, even with generics,
     *  but is only safe to do after all constructors have completed.
     */
    
    protected final void completeInit(){
        this.detailaware.add(MyThings);        
    }
    
    protected final int findMin(float[] a) {
        int minindex = 0;
        float min = Float.POSITIVE_INFINITY;

        for (int i = 0; i < a.length; i++)
            if (a[i] < min) {
                min = a[i];
                minindex = i;
            }

        return minindex;

    }

    /**
     * R_DrawMaskedColumnSinglePost. Used to handle some special cases where
     * cached columns get used as "masked" middle textures. Will be treated as a
     * single-run post of capped length.
     */

    /*
     * protected final void DrawCompositeColumnPost(byte[] column) { int
     * topscreen; int bottomscreen; int basetexturemid; // fixed_t int
     * topdelta=0; // Fixed value int length; basetexturemid = dc_texturemid; //
     * That's true for the whole column. dc_source = column; // for each post...
     * while (topdelta==0) { // calculate unclipped screen coordinates // for
     * post topscreen = sprtopscreen + spryscale * 0; length = column.length;
     * bottomscreen = topscreen + spryscale * length; dc_yl = (topscreen +
     * FRACUNIT - 1) >> FRACBITS; dc_yh = (bottomscreen - 1) >> FRACBITS; if
     * (dc_yh >= mfloorclip[p_mfloorclip + dc_x]) dc_yh =
     * mfloorclip[p_mfloorclip + dc_x] - 1; if (dc_yl <=
     * mceilingclip[p_mceilingclip + dc_x]) dc_yl = mceilingclip[p_mceilingclip
     * + dc_x] + 1; // killough 3/2/98, 3/27/98: Failsafe against
     * overflow/crash: if (dc_yl <= dc_yh && dc_yh < viewheight) { // Set
     * pointer inside column to current post's data // Rremember, it goes
     * {postlen}{postdelta}{pad}[data]{pad} dc_source_ofs = 0; // pointer + 3;
     * dc_texturemid = basetexturemid - (topdelta << FRACBITS); // Drawn by
     * either R_DrawColumn // or (SHADOW) R_DrawFuzzColumn. dc_texheight=0; //
     * Killough try { maskedcolfunc.invoke(); } catch (Exception e){
     * System.err.printf("Error rendering %d %d %d\n", dc_yl,dc_yh,dc_yh-dc_yl);
     * } } topdelta--; } dc_texturemid = basetexturemid; }
     */

    protected abstract void InitColormaps()
            throws IOException;

    // Only used b
    protected byte[] BLURRY_MAP;

    /**
     * R_InitData Locates all the lumps that will be used by all views Must be
     * called after W_Init.
     */

    public void InitData() {
        try {
            System.out.print("\nInit Texture and Flat Manager");
            TexMan = this.DM.TM;
            System.out.print("\nInitTextures");
            TexMan.InitTextures();
            System.out.print("\nInitFlats");
            TexMan.InitFlats();
            System.out.print("\nInitSprites");
            SM.InitSpriteLumps();
            MyThings.cacheSpriteManager(SM);
            VIS.cacheSpriteManager(SM);
            System.out.print("\nInitColormaps");
            InitColormaps();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    protected int spritememory;

    /**
     * To be called right after PrecacheLevel from SetupLevel in LevelLoader.
     * It's an ugly hack, in that it must communicate with the "Game map" class
     * and determine what kinds of monsters are actually in the level and
     * whether it should load their graphics or not. Whenever we implement it,
     * it's going to be ugly and not neatly separated anyway.
     * 
     * @return
     */
    public void PreCacheThinkers() {

        boolean[] spritepresent;
        thinker_t th;
        spriteframe_t sf;
        int i, j, k;
        int lump;

        final spritedef_t[] sprites = SM.getSprites();
        final int numsprites = SM.getNumSprites();

        spritepresent = new boolean[numsprites];

        for (th = P.getThinkerCap().next; th != P.getThinkerCap(); th = th.next) {
            if (th.function == think_t.P_MobjThinker)
                spritepresent[((mobj_t) th).sprite.ordinal()] = true;
        }

        spritememory = 0;
        for (i = 0; i < numsprites; i++) {
            if (!spritepresent[i])
                continue;

            for (j = 0; j < sprites[i].numframes; j++) {
                sf = sprites[i].spriteframes[j];
                for (k = 0; k < 8; k++) {
                    lump = SM.getFirstSpriteLump() + sf.lump[k];
                    spritememory += W.GetLumpInfo(lump).size;
                    W.CacheLumpNum(lump, PU_CACHE, patch_t.class);
                }
            }
        }
    }

    /**
     * R_InitTranslationTables Creates the translation tables to map the green
     * color ramp to gray, brown, red. Assumes a given structure of the PLAYPAL.
     * Could be read from a lump instead.
     */

    protected final void InitTranslationTables() {
        int i;

        final int TR_COLORS = 28;

        // translationtables = Z_Malloc (256*3+255, PU_STATIC, 0);
        // translationtables = (byte *)(( (int)translationtables + 255 )& ~255);
        byte[][] translationtables =
            colormaps.translationtables = new byte[TR_COLORS][256];

        // translate just the 16 green colors
        for (i = 0; i < 256; i++) {
            translationtables[0][i] = (byte) i;

            if (i >= 0x70 && i <= 0x7f) {
                // Remap green range to other ranges.
                translationtables[1][i] = (byte) (0x60 + (i & 0xf)); // gray
                translationtables[2][i] = (byte) (0x40 + (i & 0xf)); // brown
                translationtables[3][i] = (byte) (0x20 + (i & 0xf)); // red
                translationtables[4][i] = (byte) (0x10 + (i & 0xf)); // pink
                translationtables[5][i] = (byte) (0x30 + (i & 0xf)); // skin
                translationtables[6][i] = (byte) (0x50 + (i & 0xf)); // metal
                translationtables[7][i] = (byte) (0x80 + (i & 0xf)); // copper
                translationtables[8][i] = (byte) (0xB0 + (i & 0xf)); // b.red
                translationtables[9][i] = (byte) (0xC0 + (i & 0xf)); // electric
                                                                     // blue
                translationtables[10][i] = (byte) (0xD0 + (i & 0xf)); // guantanamo
                // "Halfhue" colors for which there are only 8 distinct hues
                translationtables[11][i] = (byte) (0x90 + (i & 0xf) / 2); // brown2
                translationtables[12][i] = (byte) (0x98 + (i & 0xf) / 2); // gray2
                translationtables[13][i] = (byte) (0xA0 + (i & 0xf) / 2); // piss
                translationtables[14][i] = (byte) (0xA8 + (i & 0xf) / 2); // gay
                translationtables[15][i] = (byte) (0xE0 + (i & 0xf) / 2); // yellow
                translationtables[16][i] = (byte) (0xE8 + (i & 0xf) / 2); // turd
                translationtables[17][i] = (byte) (0xF0 + (i & 0xf) / 2); // compblue
                translationtables[18][i] = (byte) (0xF8 + (i & 0xf) / 2); // whore
                translationtables[19][i] = (byte) (0x05 + (i & 0xf) / 2); // nigga
                // "Pimped up" colors, using mixed hues.
                translationtables[20][i] = (byte) (0x90 + (i & 0xf)); // soldier
                translationtables[21][i] = (byte) (0xA0 + (i & 0xf)); // drag
                                                                      // queen
                translationtables[22][i] = (byte) (0xE0 + (i & 0xf)); // shit &
                                                                      // piss
                translationtables[23][i] = (byte) (0xF0 + (i & 0xf)); // raver
                translationtables[24][i] = (byte) (0x70 + (0xf - i & 0xf)); // inv.marine
                translationtables[25][i] = (byte) (0xF0 + (0xf - i & 0xf)); // inv.raver
                translationtables[26][i] = (byte) (0xE0 + (0xf - i & 0xf)); // piss
                                                                            // &
                                                                            // shit
                translationtables[27][i] = (byte) (0xA0 + (i & 0xf)); // shitty
                                                                      // gay
            } else {
                for (int j = 1; j < TR_COLORS; j++)
                    // Keep all other colors as is.
                    translationtables[j][i] = (byte) i;
            }
        }
    }

    // ///////////////// Generic rendering methods /////////////////////

    public IMaskedDrawer<T, V> getThings() {
        return this.MyThings;        
    }

    /**
     * e6y: this is a precalculated value for more precise flats drawing (see
     * R_MapPlane) "Borrowed" from PrBoom+
     */
    protected float viewfocratio;

    protected int projectiony;

    // Some more isolation methods....

    public final int getValidCount() {
        return validcount;
    }

    public final void increaseValidCount(int amount) {
        validcount += amount;
    }

    public boolean getSetSizeNeeded() {
        return setsizeneeded;
    }

    @Override
    public TextureManager<T> getTextureManager() {
        return TexMan;
    }

    public PlaneDrawer<T, V> getPlaneDrawer() {
        return this.MyPlanes;
    }

    public ViewVars getView() {
        return this.view;
    }

    public SpanVars<T, V> getDSVars() {
        return this.dsvars;
    }

    public LightsAndColors<V> getColorMap() {
        return this.colormaps;
    }

    public IDoomSystem getDoomSystem() {
        return this.I;
    }

    public Visplanes getVPVars() {
        return this.vp_vars;
    }

    @Override
    public SegVars getSegVars() {
        return this.seg_vars;
    }

    public IWadLoader getWadLoader() {
        return this.W;
    }
    
    public ISpriteManager getSpriteManager(){
        return this.SM;
    }

    public BSPVars getBSPVars(){
        return this.MyBSP;
    }

    public IVisSpriteManagement<V> getVisSpriteManager(){
        return this.VIS;
    }

    // //////////////VIDEO SCALE STUFF ///////////////////////

    protected int SCREENWIDTH;

    protected int SCREENHEIGHT;

    protected float SCREEN_MUL;

    protected IVideoScale vs;

    @Override
    public void setVideoScale(IVideoScale vs) {
        this.vs = vs;
    }

    @Override
    public void initScaling() {
        this.SCREENHEIGHT = vs.getScreenHeight();
        this.SCREENWIDTH = vs.getScreenWidth();
        this.SCREEN_MUL = vs.getScreenMul();

        // Pre-scale stuff.

        view.negonearray = new short[SCREENWIDTH]; // MAES: in scaling
        view.screenheightarray = new short[SCREENWIDTH];// MAES: in scaling
        // Mirror in view
        view.xtoviewangle = xtoviewangle = new long[SCREENWIDTH + 1];

        // Initialize children objects\
        MySegs.setVideoScale(vs);
        MyPlanes.setVideoScale(vs);
        vp_vars.setVideoScale(vs);
        MyThings.setVideoScale(vs);

        MySegs.initScaling();
        MyPlanes.initScaling();
        vp_vars.initScaling();
        MyThings.initScaling();

    }

    /**
     * Initializes the various drawing functions. They are all "pegged" to the
     * same dcvars/dsvars object. Any initializations of e.g. parallel renderers
     * and their supporting subsystems should occur here.
     */

    protected void R_InitDrawingFunctions(){
        this.setHiColFuns();
        this.setLowColFuns();
    }

    // //////////////////////////// LIMIT RESETTING //////////////////
    @Override
    public void resetLimits() {
        // Call it only at the beginning of new levels.
        VIS.resetLimits();
        MySegs.resetLimits();
    }

    /**
     * R_RenderView As you can guess, this renders the player view of a
     * particular player object. In practice, it could render the view of any
     * mobj too, provided you adapt the SetupFrame method (where the viewing
     * variables are set). This is the "vanilla" implementation which just works
     * for most cases.
     */

    public void RenderPlayerView(player_t player) {

        // Viewing variables are set according to the player's mobj. Interesting
        // hacks like
        // free cameras or monster views can be done.

		/* Uncommenting this will result in a very existential experience.
		 * Basically, the player's view will randomly switch between different mobj_t's in the map, 
		 * "possessing" them at the same time and turning them into (partial) Doomguys. Limited
		 * control is possible (e.g. moving) but trying to use things or shoot while in this state will
		 * result in a NPE.
		 */
    	
    /*
  	if (Math.random()>0.99){
	  thinker_t shit=P.getRandomThinker();
	  try {		  
	  mobj_t crap=(mobj_t)shit; // It works, because practically all thinkers are also mobj_t's. There are no "bodyless" thinkers
	  player.mo=crap;
	  SetupFrame(crap);
	  } catch (ClassCastException e){

	  }
  	} else{
    
        SetupFrame(player);
  	}
  	*/
  	

        // Clear buffers.
        MyBSP.ClearClipSegs();
        seg_vars.ClearDrawSegs();
        vp_vars.ClearPlanes();
        MySegs.ClearClips();
        VIS.ClearSprites();

        // Check for new console commands.
        DGN.NetUpdate();

        // The head node is the last node output.
        MyBSP.RenderBSPNode(LL.numnodes - 1);

        // Check for new console commands.
        DGN.NetUpdate();

        // FIXME: "Warped floor" fixed, now to fix same-height visplane
        // bleeding.
        MyPlanes.DrawPlanes();

        // Check for new console commands.
        DGN.NetUpdate();

        MyThings.DrawMasked();

        colfunc.main = colfunc.base;

        // Check for new console commands.
        DGN.NetUpdate();
    }

}

package rr;

import static m.fixed_t.FRACBITS;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import p.Resettable;

import w.CacheableDoomObject;

/** This is the vertex structure used IN MEMORY with fixed-point arithmetic.
 *  It's DIFFERENT than the one used on disk, which has 16-bit signed shorts.
 *  However, it must be parsed. 
 *
 */

public class vertex_t  implements CacheableDoomObject, Resettable{

    public vertex_t(){
        
    }
    /** treat as (fixed_t) */
    public  int x,y;
    
    
    /** Notice how we auto-expand to fixed_t */
    @Override
    public void unpack(ByteBuffer buf)
            throws IOException {
        buf.order(ByteOrder.LITTLE_ENDIAN);
        this.x=buf.getShort()<<FRACBITS;
        this.y=buf.getShort()<<FRACBITS;
        
    }

    @Override
    public void reset() {
        x=0; y=0;        
    }


    public static int sizeOf() {
        return 4;
    }
    
}
package rr;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Utilities to synthesize patch_t format images from multiple patches
 * (with transparency).
 * 
 * 
 * @author velktron
 *
 */

public class MultiPatchSynthesizer {

    
    static class PixelRange {
        public PixelRange(int start, int end) {
            this.start=start;
            this.end=end;
        }
        
        public int getLength(){
            return (end-start+1);
        }
        
        public int start;
        public int end;
    }
    
    public static patch_t synthesizePatchFromFlat(String name,byte[] flat, int width, int height){
        
        byte[] expected=new byte[width *height];        
        byte[][] pixels=new byte[width][height];
        boolean[][] solid=new boolean[width][height];
        
        // Copy as much data as possible.
        System.arraycopy(flat,0,expected,0,Math.min(flat.length,expected.length));

        for (int i=0;i<width;i++){           
            Arrays.fill(solid[i],true);
            for (int j=0;j<height;j++){
                pixels[i][j]=expected[i+j*width];
            }
        }
        
        patch_t result=new patch_t(name,width,height,0,0);
        column_t[] columns=new column_t[width];
        
        for (int x=0;x<width;x++)
            columns[x]=getColumnStream(pixels[x],solid[x],height);
        
       result.columns=columns;
        return result;
    }
    
    public static patch_t synthesize(String name,byte[][] pixels, boolean[][] solid, int width, int height){
        
        patch_t result=new patch_t(name,width,height,0,0);
        column_t[] columns=new column_t[width];
        
        for (int x=0;x<width;x++)
            columns[x]=getColumnStream(pixels[x],solid[x],height);
        
       result.columns=columns;
        return result;
    }

    public static column_t getColumnStream(byte[] pixels, boolean[] solid, int height){
    
        column_t result=new column_t();
        int start=-1;
        int end=-1;
        
        List<PixelRange> ranges=new ArrayList<PixelRange>();
        
        // Scan column for continuous pixel ranges                
        for (int i=0;i<height;i++){
            
            // Encountered solid start.
            if (solid[i] && start==-1){
                start=i; // mark start
            }
                
            // Last solid pixel
            if (solid[i] && i==height-1 && start!=-1 ){
                end=i;
                ranges.add(new PixelRange(start,end));
                start=end=-1; // reset start/end
            }
               
            // Start defined and ending not yet detected
            if (!solid[i] && start!=-1 && end ==-1){
                end=i-1; // Single-pixel runs would be e.g. 1-2 -> 1-1
            }            

            if (start!=-1 && end!=-1){
                // Range complete.
                ranges.add(new PixelRange(start,end));
                start=end=-1; // reset start/end
            }
        }
        
        // There should be at least an empty post
        if (ranges.size()==0){
            ranges.add(new PixelRange(0,-1));
        }
        
        // Ideal for this use, since we don't know how big the patch is going to be a-priori
        ByteArrayOutputStream file=new ByteArrayOutputStream();
        int topdelta=0;
        int n=ranges.size();
        short topdeltas[]=new short[n];
        int postofs[]=new int[n];
        short postlens[]=new short[n];
        

        
        for (int i=0;i<n;i++){
            PixelRange pr=ranges.get(i);
            topdelta=pr.start; // cumulative top delta  
            
            // Precomputed column data
            postofs[i]=(short) file.size()+3; // Last written post +3, pointing at first pixel of data.
            topdeltas[i]=(short) topdelta;
            postlens[i]=(short) (pr.getLength()); // Post lengths are at net of padding  
                      
            file.write(topdeltas[i]);
            file.write(postlens[i]);
            file.write(0); // padding
            file.write(pixels,pr.start,pr.getLength()); // data
            file.write(0); // padding
            }
    
        file.write(0xFF); // Terminator
        
        result.data=file.toByteArray();
        result.postdeltas=topdeltas;
        result.postlen=postlens;
        result.postofs=postofs;
        result.posts=ranges.size();
        
        // The ranges tell us where continuous posts
        
        return result;
    }
    
    /*
    public static patch_t synthesize(byte[][] pixels, boolean[][] solid, int width, int height, int picture_top, int picture_left){
        // Ideal for this use, since we don't know how big the patch is going to be a-priori
        ByteArrayOutputStream file=new ByteArrayOutputStream();
        
        int offset;
        
        int[] columnofs=new int[width];
        
        // Patch header
        file.write(width);
        file.write(height);
        file.write(picture_top);
        file.write(picture_left);

        int column_array=0;
        int x=0,y;
        byte dummy_value;
        while (x<width){

            //write memory buffer position to end of column_array
            columnofs[column_array]=file.size();
            column_array++;

            y = 0;

            boolean operator = true;
            int pixel_count = 0;
            
            while (y < height){
                byte val=pixels[x][y];
                boolean transparent=!solid[x][y];
                
                
                // Pixel is transparent
                if (transparent && !operator ) {
                    dummy_value = 0;                    
                    file.write(dummy_value);
                    operator = true;
                    }
                else //Pixel not transparent, and operator condition set.
                    if (!transparent && operator){
                    int row_start = y;                    
                    pixel_count = 0;
                    dummy_value = 0;
                    // write above post data to memory buffer

                    offset = file.size(); //current post position in memory buffer

                    operator = false;
                    } else 
                   if (!transparent && !operator){
                       pixel_count++; // increment current post pixel_count
                   }

                    if (offset > 0 && pixel_count > 0){
                        previous_offset = current post position

                        seek back in memory buffer by offset - 2

                        write pixel_count to memory buffer

                        seek back to previous_offset
                    end block
                    
                    write pixel to memory buffer
                end block

                increment y by 1

            end block

            if operator = true or y = height then
                Pixel = 0

                write Pixel to memory buffer

                rowstart = 255
                
                write rowstart to memory buffer
            end block

            increment x by 1

        end block

        seek memory buffer position to 0

        block_size = picture_width * size of dword

        allocate block_memory, filled with 0's, with block_size

        write block_memory to file, using block_size as size

        offset = current file_position

        free block_memory

        seek to position 8 in file from start

        for loop, count = 0, break on count = number of elements in column_array
            column_offset = column_array[count] + offset

            write column_offset to file
        end block

        write memory buffer to file
    }
    } */
    
}

package rr;

/** Interface for sprite managers. Handles loading sprites, fixing
 *  rotations etc. and helping retrieving spritedefs when required.
 * 
 * @author velktron.
 *
 */

public interface ISpriteManager {
    
    /** Default known sprite names for DOOM */
    public final static String[] doomsprnames = {
        "TROO","SHTG","PUNG","PISG","PISF","SHTF","SHT2","CHGG","CHGF","MISG",
        "MISF","SAWG","PLSG","PLSF","BFGG","BFGF","BLUD","PUFF","BAL1","BAL2",
        "PLSS","PLSE","MISL","BFS1","BFE1","BFE2","TFOG","IFOG","PLAY","POSS",
        "SPOS","VILE","FIRE","FATB","FBXP","SKEL","MANF","FATT","CPOS","SARG",
        "HEAD","BAL7","BOSS","BOS2","SKUL","SPID","BSPI","APLS","APBX","CYBR",
        "PAIN","SSWV","KEEN","BBRN","BOSF","ARM1","ARM2","BAR1","BEXP","FCAN",
        "BON1","BON2","BKEY","RKEY","YKEY","BSKU","RSKU","YSKU","STIM","MEDI",
        "SOUL","PINV","PSTR","PINS","MEGA","SUIT","PMAP","PVIS","CLIP","AMMO",
        "ROCK","BROK","CELL","CELP","SHEL","SBOX","BPAK","BFUG","MGUN","CSAW",
        "LAUN","PLAS","SHOT","SGN2","COLU","SMT2","GOR1","POL2","POL5","POL4",
        "POL3","POL1","POL6","GOR2","GOR3","GOR4","GOR5","SMIT","COL1","COL2",
        "COL3","COL4","CAND","CBRA","COL6","TRE1","TRE2","ELEC","CEYE","FSKU",
        "COL5","TBLU","TGRN","TRED","SMBT","SMGT","SMRT","HDB1","HDB2","HDB3",
        "HDB4","HDB5","HDB6","POB1","POB2","BRS1","TLMP","TLP2"
    };
    
    void InitSpriteLumps();
    
    int getNumSprites();

    int getFirstSpriteLump();
    
    spritedef_t[] getSprites();
    
    spritedef_t getSprite(int index);
    
    int[] getSpriteWidth();
    int[] getSpriteOffset();
    int[] getSpriteTopOffset();

    int getSpriteWidth(int index);
    int getSpriteOffset(int index);
    int getSpriteTopOffset(int index);

    void InitSprites(String[] namelist);

    
}
package rr;

import p.Resettable;

/**
 * 
 * A SubSector. References a Sector. Basically, this is a list of LineSegs,
 * indicating the visible walls that define (all or some) sides of a convex BSP
 * leaf.
 * 
 * @author admin
 */
public class subsector_t implements Resettable{

	public subsector_t() {
		this(null,  0,  0);
	} 

	public subsector_t(sector_t sector, int numlines, int firstline) {
		this.sector = sector;
		this.numlines = numlines;
		this.firstline = firstline;
	}

	// Maes: single pointer
	public sector_t sector;
	// e6y: support for extended nodes
	// 'int' instead of 'short'
	public int numlines;
	public int firstline;
	
	public String toString(){
		sb.setLength(0);
		sb.append("Subsector");
		sb.append('\t');
		sb.append("Sector: ");
		sb.append(sector);
		sb.append('\t');
		sb.append("numlines ");
		sb.append(numlines);
		sb.append('\t');
		sb.append("firstline ");
		sb.append(firstline);
		return sb.toString();
		
		
	}
	
	private static StringBuilder sb=new StringBuilder();

    @Override
    public void reset() {
        sector=null;
        firstline=numlines=0;        
    }
	

}

package rr;

/**
 * A single patch from a texture definition,
 * basically a rectangular area within
 * the texture rectangle.
 * @author admin
 *
 */
public class texpatch_t {
// Block origin (allways UL),
// which has allready accounted
// for the internal origin of the patch.
int     originx;    
int     originy;
int     patch;

public void copyFromMapPatch(mappatch_t mpp) {
   this.originx=mpp.originx;
   this.originy=mpp.originy;
   this.patch=mpp.patch;
    }
}
package rr;

import static data.Defines.FF_FRAMEMASK;
import static data.Defines.FF_FULLBRIGHT;
import static data.Limits.MAXVISSPRITES;
import static data.Tables.ANG45;
import static data.Tables.BITS32;
import static m.fixed_t.FRACBITS;
import static m.fixed_t.FRACUNIT;
import static m.fixed_t.FixedDiv;
import static m.fixed_t.FixedMul;
import static p.mobj_t.MF_SHADOW;
import static rr.LightsAndColors.*;
import static rr.Renderer.MINZ;

import i.IDoomSystem;

import java.util.Arrays;

import p.mobj_t;
import utils.C2JUtils;

/** Visualized sprite manager. Depends on: SpriteManager, DoomSystem,
 *  Colormaps, Current View.
 *  
 * @author velktron
 *
 * @param <V>
 */

public final class VisSprites<V>
        implements IVisSpriteManagement<V> {

    private final static boolean DEBUG = false;

    private final static boolean RANGECHECK = false;

    protected IDoomSystem I;

    protected ISpriteManager SM;

    protected ViewVars view;

    protected LightsAndColors<V> colormaps;

    protected RendererState<?, V> R;

    public VisSprites(RendererState<?, V> R) {
        updateStatus(R);
        vissprite_t<V> tmp = new vissprite_t<V>();
        vissprites = C2JUtils.createArrayOfObjects(tmp, MAXVISSPRITES);
    }

    public void updateStatus(RendererState<?, V> R) {
        this.R = R;
        this.view = R.view;
        this.I = R.I;
        this.SM = R.SM;
        this.colormaps = R.colormaps;

    }

    protected vissprite_t<V>[] vissprites;

    protected int vissprite_p;

    protected int newvissprite;

    // UNUSED
    // private final vissprite_t unsorted;
    // private final vissprite_t vsprsortedhead;

    // Cache those you get from the sprite manager
    protected int[] spritewidth, spriteoffset, spritetopoffset;

    /**
     * R_AddSprites During BSP traversal, this adds sprites by sector.
     */

    @Override
    public void AddSprites(sector_t sec) {
        if (DEBUG)
            System.out.println("AddSprites");
        mobj_t thing;
        int lightnum;

        // BSP is traversed by subsector.
        // A sector might have been split into several
        // subsectors during BSP building.
        // Thus we check whether its already added.
        if (sec.validcount == R.getValidCount())
            return;

        // Well, now it will be done.
        sec.validcount = R.getValidCount();

        lightnum = (sec.lightlevel >> LIGHTSEGSHIFT) + colormaps.extralight;

        if (lightnum < 0)
            colormaps.spritelights = colormaps.scalelight[0];
        else if (lightnum >= LIGHTLEVELS)
            colormaps.spritelights = colormaps.scalelight[LIGHTLEVELS - 1];
        else
            colormaps.spritelights = colormaps.scalelight[lightnum];

        // Handle all things in sector.
        for (thing = sec.thinglist; thing != null; thing = (mobj_t) thing.snext)
            ProjectSprite(thing);
    }

    /**
     * R_ProjectSprite Generates a vissprite for a thing if it might be visible.
     * 
     * @param thing
     */
    protected final void ProjectSprite(mobj_t thing) {
        int tr_x, tr_y;
        int gxt, gyt;
        int tx, tz;

        int xscale, x1, x2;

        spritedef_t sprdef;
        spriteframe_t sprframe;
        int lump;

        int rot;
        boolean flip;

        int index;

        vissprite_t<V> vis;

        long ang;
        int iscale;

        // transform the origin point
        tr_x = thing.x - view.x;
        tr_y = thing.y - view.y;

        gxt = FixedMul(tr_x, view.cos);
        gyt = -FixedMul(tr_y, view.sin);

        tz = gxt - gyt;

        // thing is behind view plane?
        if (tz < MINZ)
            return;
        /* MAES: so projection/tz gives horizontal scale */
        xscale = FixedDiv(view.projection, tz);

        gxt = -FixedMul(tr_x, view.sin);
        gyt = FixedMul(tr_y, view.cos);
        tx = -(gyt + gxt);

        // too far off the side?
        if (Math.abs(tx) > (tz << 2))
            return;

        // decide which patch to use for sprite relative to player
        if (RANGECHECK) {
            if (thing.sprite.ordinal() >= SM.getNumSprites())
                I.Error("R_ProjectSprite: invalid sprite number %d ",
                    thing.sprite);
        }
        sprdef = SM.getSprite(thing.sprite.ordinal());
        if (RANGECHECK) {
            if ((thing.frame & FF_FRAMEMASK) >= sprdef.numframes)
                I.Error("R_ProjectSprite: invalid sprite frame %d : %d ",
                    thing.sprite, thing.frame);
        }
        sprframe = sprdef.spriteframes[thing.frame & FF_FRAMEMASK];

        if (sprframe.rotate != 0) {
            // choose a different rotation based on player view
            ang = view.PointToAngle(thing.x, thing.y);
            rot = (int) ((ang - thing.angle + (ANG45 * 9) / 2) & BITS32) >>> 29;
            lump = sprframe.lump[rot];
            flip = (boolean) (sprframe.flip[rot] != 0);
        } else {
            // use single rotation for all views
            lump = sprframe.lump[0];
            flip = (boolean) (sprframe.flip[0] != 0);
        }

        // calculate edges of the shape
        tx -= spriteoffset[lump];
        x1 = (view.centerxfrac + FixedMul(tx, xscale)) >> FRACBITS;

        // off the right side?
        if (x1 > view.width)
            return;

        tx += spritewidth[lump];
        x2 = ((view.centerxfrac + FixedMul(tx, xscale)) >> FRACBITS) - 1;

        // off the left side
        if (x2 < 0)
            return;

        // store information in a vissprite
        vis = NewVisSprite();
        vis.mobjflags = thing.flags;
        vis.scale = xscale << view.detailshift;
        vis.gx = thing.x;
        vis.gy = thing.y;
        vis.gz = thing.z;
        vis.gzt = thing.z + spritetopoffset[lump];
        vis.texturemid = vis.gzt - view.z;
        vis.x1 = x1 < 0 ? 0 : x1;
        vis.x2 = x2 >= view.width ? view.width - 1 : x2;
        /*
         * This actually determines the general sprite scale) iscale = 1/xscale,
         * if this was floating point.
         */
        iscale = FixedDiv(FRACUNIT, xscale);

        if (flip) {
            vis.startfrac = spritewidth[lump] - 1;
            vis.xiscale = -iscale;
        } else {
            vis.startfrac = 0;
            vis.xiscale = iscale;
        }

        if (vis.x1 > x1)
            vis.startfrac += vis.xiscale * (vis.x1 - x1);
        vis.patch = lump;

        // get light level
        if ((thing.flags & MF_SHADOW) != 0) {
            // shadow draw
            vis.colormap = null;
        } else if (colormaps.fixedcolormap != null) {
            // fixed map
            vis.colormap = (V) colormaps.fixedcolormap;
            // vis.pcolormap=0;
        } else if ((thing.frame & FF_FULLBRIGHT) != 0) {
            // full bright
            vis.colormap = (V) colormaps.colormaps[0];
            // vis.pcolormap=0;
        }

        else {
            // diminished light
            index = xscale >> (LIGHTSCALESHIFT - view.detailshift);

            if (index >= MAXLIGHTSCALE)
                index = MAXLIGHTSCALE - 1;

            vis.colormap = colormaps.spritelights[index];
            // vis.pcolormap=index;
        }
    }

    /**
     * R_NewVisSprite Returns either a "new" sprite (actually, reuses a pool),
     * or a special "overflow sprite" which just gets overwritten with bogus
     * data. It's a bit of dumb thing to do, since the overflow sprite is never
     * rendered but we have to copy data over it anyway. Would make more sense
     * to check for it specifically and avoiding copying data, which should be
     * more time consuming. Fixed by making this fully limit-removing.
     * 
     * @return
     */
    protected final vissprite_t<V> NewVisSprite() {
        if (vissprite_p == (vissprites.length - 1)) {
            ResizeSprites();
        }
        // return overflowsprite;

        vissprite_p++;
        return vissprites[vissprite_p - 1];
    }

    @Override
    public void cacheSpriteManager(ISpriteManager SM) {
        this.spritewidth = SM.getSpriteWidth();
        this.spriteoffset = SM.getSpriteOffset();
        this.spritetopoffset = SM.getSpriteTopOffset();
    }

    /**
     * R_ClearSprites Called at frame start.
     */

    @Override
    public void ClearSprites() {
        // vissprite_p = vissprites;
        vissprite_p = 0;
    }

    // UNUSED private final vissprite_t overflowsprite = new vissprite_t();

    protected final void ResizeSprites() {
        vissprites =
            C2JUtils.resize(vissprites[0], vissprites, vissprites.length * 2); // Bye
                                                                               // bye,
                                                                               // old
                                                                               // vissprites.
    }

    /**
     * R_SortVisSprites UNUSED more efficient Comparable sorting + built-in
     * Arrays.sort function used.
     */

    @Override
    public final void SortVisSprites() {
        Arrays.sort(vissprites, 0, vissprite_p);

        // Maes: got rid of old vissprite sorting code. Java's is better
        // Hell, almost anything was better than that.

    }

    @Override
    public int getNumVisSprites() {
        return vissprite_p;
    }

    @Override
    public vissprite_t<V>[] getVisSprites() {
        return vissprites;
    }

    public void resetLimits() {
        vissprite_t<V>[] tmp =
            C2JUtils.createArrayOfObjects(vissprites[0], MAXVISSPRITES);
        System.arraycopy(vissprites, 0, tmp, 0, MAXVISSPRITES);

        // Now, that was quite a haircut!.
        vissprites = tmp;    }
}
package rr;

import static m.fixed_t.FRACBITS;
import static m.fixed_t.FixedMul;

import p.Resettable;

/**
 * The LineSeg. Must be built from on-disk mapsegs_t, which are much simpler.
 * 
 * @author Maes
 */

public class seg_t
        implements Resettable {

    /** To be used as references */
    public vertex_t v1, v2;

    /** Local caching. Spares us using one extra reference level */
    public int v1x, v1y, v2x, v2y;

    /** (fixed_t) */
    public int offset;

    /** (angle_t) */
    public long angle;

    // MAES: all were single pointers.

    public side_t sidedef;

    public line_t linedef;

    /**
     * Sector references. Could be retrieved from linedef, too. backsector is
     * NULL for one sided lines
     */
    public sector_t frontsector, backsector;

    // Boom stuff
    public boolean miniseg;

    public float length;

    /** proff 11/05/2000: needed for OpenGL */
    public int iSegID;

    public void assignVertexValues() {
        this.v1x = v1.x;
        this.v1y = v1.y;
        this.v2x = v2.x;
        this.v2y = v2.y;

    }

    /**
     * R_PointOnSegSide
     * 
     * @param x
     * @param y
     * @param line
     * @return
     */
    public static int PointOnSegSide(int x, int y, seg_t line) {
        int lx;
        int ly;
        int ldx;
        int ldy;
        int dx;
        int dy;
        int left;
        int right;

        lx = line.v1x;
        ly = line.v1y;

        ldx = line.v2x - lx;
        ldy = line.v2y - ly;

        if (ldx == 0) {
            if (x <= lx)
                return (ldy > 0) ? 1 : 0;

            return (ldy < 0) ? 1 : 0;
        }
        if (ldy == 0) {
            if (y <= ly)
                return (ldx < 0) ? 1 : 0;

            return (ldx > 0) ? 1 : 0;
        }

        dx = x - lx;
        dy = y - ly;

        // Try to quickly decide by looking at sign bits.
        if (((ldy ^ ldx ^ dx ^ dy) & 0x80000000) != 0) {
            if (((ldy ^ dx) & 0x80000000) != 0) {
                // (left is negative)
                return 1;
            }
            return 0;
        }

        left = FixedMul(ldy >> FRACBITS, dx);
        right = FixedMul(dy, ldx >> FRACBITS);

        if (right < left) {
            // front side
            return 0;
        }
        // back side
        return 1;
    }

    /**
     * R_PointOnSegSide
     * 
     * @param x
     * @param y
     * @param line
     * @return
     */
    public int PointOnSegSide(int x, int y) {
        int lx;
        int ly;
        int ldx;
        int ldy;
        int dx;
        int dy;
        int left;
        int right;

        lx = this.v1x;
        ly = this.v1y;

        ldx = this.v2x - lx;
        ldy = this.v2y - ly;

        if (ldx == 0) {
            if (x <= lx)
                return (ldy > 0) ? 1 : 0;

            return (ldy < 0) ? 1 : 0;
        }
        if (ldy == 0) {
            if (y <= ly)
                return (ldx < 0) ? 1 : 0;

            return (ldx > 0) ? 1 : 0;
        }

        dx = x - lx;
        dy = y - ly;

        // Try to quickly decide by looking at sign bits.
        if (((ldy ^ ldx ^ dx ^ dy) & 0x80000000) != 0) {
            if (((ldy ^ dx) & 0x80000000) != 0) {
                // (left is negative)
                return 1;
            }
            return 0;
        }

        left = FixedMul(ldy >> FRACBITS, dx);
        right = FixedMul(dy, ldx >> FRACBITS);

        if (right < left) {
            // front side
            return 0;
        }
        // back side
        return 1;
    }

    public String toString() {
        return String
                .format(
                    "Seg %d\n\tFrontsector: %s\n\tBacksector: %s\n\tVertexes: %x %x %x %x",
                    iSegID, frontsector, backsector, v1x, v1y, v2x, v2y);
    }

    @Override
    public void reset() {
        v1 = v2 = null;
        v1x = v1y = v2x = v2y = 0;
        angle = 0;
        frontsector = backsector = null;
        iSegID = 0;
        linedef = null;
        miniseg = false;
        offset = 0;
        length = 0;
    }

}

package rr;

import static data.Tables.ANGLETOFINESHIFT;
import static data.Tables.BITS32;
import static data.Tables.finecosine;
import static data.Tables.finesine;
import static m.fixed_t.FixedMul;
import static rr.LightsAndColors.*;

import i.IDoomSystem;

import rr.RendererState.IPlaneDrawer;
import rr.drawfuns.SpanVars;
import v.IVideoScale;

public abstract class PlaneDrawer<T,V> implements IPlaneDrawer{

    private static final boolean DEBUG2=false;


    protected final boolean RANGECHECK = false;
    
    //
    // spanstart holds the start of a plane span
    // initialized to 0 at start
    //
    protected int[] spanstart, spanstop;

    //
    // texture mapping
    //
    protected V[] planezlight; // The distance lighting effect you see
    /** To treat as fixed_t */
    protected int planeheight;
    /** To treat as fixed_t */
    protected int[] distscale;

    /** To treat as fixed_t */
    protected int[] cacheddistance, cachedxstep, cachedystep;

    protected final ViewVars view;    

    protected final SegVars seg_vars;
    protected final SpanVars<T,V> dsvars;
    /** The visplane data. Set separately. For threads, use the same for
     *  everyone.
     */
    protected Visplanes vpvars;
    protected final LightsAndColors<V> colormap;
    protected final TextureManager<T> TexMan;
    protected final IDoomSystem I;
    
    
    protected PlaneDrawer(Renderer<T,V> R){
        this.view=R.getView();
        this.vpvars=R.getVPVars();
        this.dsvars=R.getDSVars();
        this.seg_vars=R.getSegVars();
        this.colormap=R.getColorMap();
        this.TexMan=R.getTextureManager();
        this.I=R.getDoomSystem();
    }

    /**
     * R_MapPlane
     * 
     * Called only by R_MakeSpans.
     * 
     * This is where the actual span drawing function is called.
     * 
     * Uses global vars: planeheight ds_source -> flat data has already been
     * set. basexscale -> actual drawing angle and position is computed from
     * these baseyscale viewx viewy
     * 
     * BASIC PRIMITIVE
     */

    public void MapPlane(int y, int x1, int x2) {
        // MAES: angle_t
        int angle;
        // fixed_t
        int distance;
        int length;
        int index;

        if (RANGECHECK) {
            rangeCheck(x1,x2,y);
        }

        if (planeheight != vpvars.cachedheight[y]) {
            vpvars.cachedheight[y] = planeheight;
            distance = cacheddistance[y] = FixedMul(planeheight, vpvars.yslope[y]);
            dsvars.ds_xstep = cachedxstep[y] = FixedMul(distance, vpvars.basexscale);
            dsvars.ds_ystep = cachedystep[y] = FixedMul(distance, vpvars.baseyscale);
        } else {
            distance = cacheddistance[y];
            dsvars.ds_xstep = cachedxstep[y];
            dsvars.ds_ystep = cachedystep[y];
        }

        length = FixedMul(distance, distscale[x1]);
        angle = (int) (((view.angle + view.xtoviewangle[x1]) & BITS32) >>> ANGLETOFINESHIFT);
        dsvars.ds_xfrac = view.x + FixedMul(finecosine[angle], length);
        dsvars.ds_yfrac = -view.y - FixedMul(finesine[angle], length);

        if (colormap.fixedcolormap != null)
            dsvars.ds_colormap = colormap.fixedcolormap;
        else {
            index = distance >>> LIGHTZSHIFT;

            if (index >= MAXLIGHTZ)
                index = MAXLIGHTZ - 1;

            dsvars.ds_colormap = planezlight[index];
        }

        dsvars.ds_y = y;
        dsvars.ds_x1 = x1;
        dsvars.ds_x2 = x2;

        // high or low detail
        dsvars.spanfunc.invoke();
    }

    protected final void rangeCheck(int x1,int x2,int y) {
        if (x2 < x1 || x1 < 0 || x2 >= view.width || y > view.height)
            I.Error("%s: %d, %d at %d",this.getClass().getName(), x1, x2, y);
        }
  
        
    /**
     * R_MakeSpans
     * 
     * Called only by DrawPlanes. If you wondered where the actual
     * boundaries for the visplane flood-fill are laid out, this is it.
     * 
     * The system of coords seems to be defining a sort of cone.
     * 
     * 
     * @param x
     *            Horizontal position
     * @param t1
     *            Top-left y coord?
     * @param b1
     *            Bottom-left y coord?
     * @param t2
     *            Top-right y coord ?
     * @param b2
     *            Bottom-right y coord ?
     * 
     */

    protected void MakeSpans(int x, int t1, int b1, int t2, int b2) {

        // If t1 = [sentinel value] then this part won't be executed.
        while (t1 < t2 && t1 <= b1) {
            this.MapPlane(t1, spanstart[t1], x - 1);
            t1++;
        }
        while (b1 > b2 && b1 >= t1) {
            this.MapPlane(b1, spanstart[b1], x - 1);
            b1--;
        }

        // So...if t1 for some reason is < t2, we increase t2 AND store the
        // current x
        // at spanstart [t2] :-S
        while (t2 < t1 && t2 <= b2) {
            // System.out.println("Increasing t2");
            spanstart[t2] = x;
            t2++;
        }

        // So...if t1 for some reason b2 > b1, we decrease b2 AND store the
        // current x
        // at spanstart [t2] :-S

        while (b2 > b1 && b2 >= t2) {
            // System.out.println("Decreasing b2");
            spanstart[b2] = x;
            b2--;
        }
    }

    /**
     * R_InitPlanes Only at game startup.
     */

    public void InitPlanes() {
        // Doh!
    }

   /////////// VIDEO SCALE STUFF ///////////

    protected int SCREENWIDTH;
    protected int SCREENHEIGHT;
    protected IVideoScale vs;

    @Override
    public void setVideoScale(IVideoScale vs) {
        this.vs = vs;
    }

    @Override
    public void initScaling() {
        this.SCREENHEIGHT = vs.getScreenHeight();
        this.SCREENWIDTH = vs.getScreenWidth();

        // Pre-scale stuff.

        spanstart = new int[SCREENHEIGHT];
        spanstop = new int[SCREENHEIGHT];
        distscale = new int[SCREENWIDTH];        
        cacheddistance = new int[SCREENHEIGHT];
        cachedxstep = new int[SCREENHEIGHT];
        cachedystep = new int[SCREENHEIGHT];

        // HACK: visplanes are initialized globally.
        visplane_t.setVideoScale(vs);
        visplane_t.initScaling();
        vpvars.initVisplanes();

    }
    
    protected final void rangeCheckErrors(){
        if (seg_vars.ds_p > seg_vars.MAXDRAWSEGS)
            I.Error("R_DrawPlanes: drawsegs overflow (%d)", seg_vars.ds_p);

        if (vpvars.lastvisplane > vpvars.MAXVISPLANES)
            I.Error(" R_DrawPlanes: visplane overflow (%d)",
                vpvars.lastvisplane);

        if (vpvars.lastopening > vpvars.MAXOPENINGS)
            I.Error("R_DrawPlanes: opening overflow (%d)", vpvars.lastopening);
    }

    /** Default implementation which DOES NOTHING. MUST OVERRIDE */
    
    public void DrawPlanes(){
        
    }
    
    public void sync(){
        // Nothing required if serial.
    }
    
    /////////////// VARIOUS BORING GETTERS ////////////////////


    @Override
    public int[] getDistScale() {
        return distscale;
    }
    
}

package rr;

import static data.Defines.PU_CACHE;
import static data.Defines.PU_STATIC;
import static data.Defines.SKYFLATNAME;
import static m.fixed_t.FRACBITS;
import static m.fixed_t.FRACUNIT;

import i.IDoomSystem;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import p.AbstractLevelLoader;
import doom.DoomStatus;
import w.DoomBuffer;
import w.IWadLoader;
import w.li_namespace;
import w.lumpinfo_t;

/** An attempt to separate texture mapping functionality from
 *  the rest of the rendering. Seems to work like a charm, and
 *  it makes it clearer what needs and what doesn't need to be 
 *  exposed.
 * 
 * @author Maes
 *
 */

public class SimpleTextureManager
        implements TextureManager<byte[]> {
    
    IWadLoader W;
    IDoomSystem I;
    AbstractLevelLoader LL;
    DoomStatus<?,?> DM;
    
    //
    // Graphics.
    // DOOM graphics for walls and sprites
    // is stored in vertical runs of opaque pixels (posts).
    // A column is composed of zero or more posts,
    // a patch or sprite is composed of zero or more columns.
    // 

    protected int     firstflat;
    protected int     lastflat;
    protected int     numflats;
    /** HACK */
    protected flat_t[] flats;
    
    //protected int     firstpatch;
    //protected int     lastpatch;
    protected int     numpatches;


    protected int     numtextures;
    
    /** The unchached textures themselves, stored just as patch lists and various properties */
    protected texture_t[] textures;

    /** Width per texture? */
    protected int[]            texturewidthmask;
    /** fixed_t[] needed for texture pegging */
    
    /** How tall each composite texture is supposed to be */
    protected int[]        textureheight;    
    
    /** How large each composite texture is supposed to be */
    protected int[]            texturecompositesize;
    /** Tells us which patch lump covers which column of which texture */
    protected short[][]         texturecolumnlump;
    
    /** This is supposed to store indexes into a patch_t lump which point to the columns themselves 
     *  Instead, we're going to return indexes to columns inside a particular patch.
     *  In the case of patches inside a non-cached multi-patch texture (e.g. those made of non-overlapping
     *  patches), we're storing indexes INSIDE A PARTICULAR PATCH. E.g. for STARTAN1, which is made of two
     *  32-px wide patches, it should go something like 0, 1,2 ,3...31, 0,1,2,....31.
     *  
     * */
    protected char[][]    texturecolumnofs;
    
    /** couple with texturecomposite */
    protected char texturecoloffset;
    //short[][]    texturecolumnindexes;
    /** Stores [textures][columns][data]. */
    protected byte[][][] texturecomposite;
    
    /** HACK to store "composite masked textures", a Boomism. */ 
    protected patch_t[] patchcomposite;

    /** for global animation. Storage stores actual lumps, translation is a relative -> relative map */
    protected int[]        flattranslation, flatstorage,texturetranslation;
    
    // This is also in DM, but one is enough, really.
    protected int skytexture,skytexturemid,skyflatnum;
    
    public SimpleTextureManager(DoomStatus<?,?> DC) {
        this.DM=DC;
        this.W=DM.W;
        this.I=DM.I;
        this.LL=DM.LL;
        FlatPatchCache=new Hashtable<Integer, patch_t>();
    }
  
    /** Hash table used for matching flat <i>lump</i> to flat <i>num</i> */

    Hashtable<Integer, Integer> FlatCache;
    
    Hashtable<Integer, patch_t> FlatPatchCache;

      /**
       * R_CheckTextureNumForName Check whether texture is available. Filter out
       * NoTexture indicator. Can be sped up with a hash table, but it's pointless.
       */
    
        @Override
       public int CheckTextureNumForName(String name) {
          Integer i;
          // "NoTexture" marker.
          if (name.charAt(0) == '-')  return 0;
          
          i=TextureCache.get(name);
          if (i==null) return -1;
          else return i;

          /* for (i = 0; i < numtextures; i++)
              if (textures[i].name.compareToIgnoreCase(name) == 0)
                  return i;

          return -1; */
      }
    
        /** Hash table used for fast texture lookup */

        Hashtable<String, Integer> TextureCache;
        
        /**
         * R_TextureNumForName
         * Calls R_CheckTextureNumForName,
         * aborts with error message.
         */
      
        public int TextureNumForName(String name) {
            int i;

            i = CheckTextureNumForName(name);

            if (i == -1) {
                I.Error("R_TextureNumForName: %s not found", name);
            }
            return i;
        }

    /**
     * R_InitTextures
     * Initializes the texture list
     *  with the textures from the world map.
     */
    
    public void InitTextures () throws IOException
    {
        // This drives the rest
        maptexture_t mtexture = new maptexture_t();
        texture_t texture;
        mappatch_t[] mpatch;
        texpatch_t[] patch;
        ByteBuffer[] maptex = new ByteBuffer[texturelumps.length];
        int[] patchlookup;
        int totalwidth;
        int offset;
        int[] maxoff = new int[texturelumps.length];
        int[] _numtextures = new int[texturelumps.length];
        int directory = 1;
        int texset=TEXTURE1;
        // Load the patch names from pnames.lmp.
        //name[8] = 0;    
        patchlookup=loadPatchNames("PNAMES");
        
        // Load the map texture definitions from textures.lmp.
        // The data is contained in one or two lumps,
        //  TEXTURE1 for shareware, plus TEXTURE2 for commercial.
        
        for (int i=0;i<texturelumps.length;i++){
            String TEXTUREx=texturelumps[i];
            if (W.CheckNumForName (TEXTUREx) != -1){
            maptex[i] = W.CacheLumpName (TEXTUREx, PU_STATIC).getBuffer();
            maptex[i].rewind();
            maptex[i].order(ByteOrder.LITTLE_ENDIAN);
            _numtextures[i] = maptex[i].getInt();
            maxoff[i] = W.LumpLength (W.GetNumForName (TEXTUREx));
            if (_numtextures[i]!= (maxoff[i]-4)/8) {
            	System.err.printf("Warning! Possibly malformed TEXTURE%d lump. Stated number of textures: %d Possible: %d\n",i, _numtextures[i] , (maxoff[i]-4)/8);
            }
           
            }
        }
        
        // Total number of textures.
        numtextures = _numtextures[0] + _numtextures[1];
        
        textures = new texture_t[numtextures];
        // MAES: Texture hashtable.          
        TextureCache=new Hashtable<String, Integer>(numtextures);
        
        texturecolumnlump = new short[numtextures][];
        texturecolumnofs = new char[numtextures][];
        patchcomposite=new patch_t[numtextures];
        texturecomposite = new byte[numtextures][][];
        texturecompositesize = new int[numtextures];
        texturewidthmask = new int[numtextures];
        textureheight = new int[numtextures];

        totalwidth = 0;
        
        //  Really complex printing shit...
        System.out.print("[");
        for (int i=0 ; i<n