c/237: Memory chunks > 64 KB mirrors

tolf@usa.net tolf@usa.net
Tue May 23 12:56:00 GMT 2000


>Number:         237
>Category:       c
>Synopsis:       Memory chunks > 64 KB mirrors
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Tue May 23 12:56:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Fredrik Tolf
>Release:        2.95.2 19991024
>Organization:
>Environment:
Windows 95, Intel 486-DX 50 MHz, 16 MB RAM
DJGPP is executed over network, mapped path = Z:\DJGPP
>Description:
I allocate two memory chunks, 6.4 MB each, but as I try to write to one of them, I can only write in the first 64 KB area, and the data is mirrored every 65536th byte forward. The program is translated from a real-mode program, so I guess the problem might lie there, but I've been unable to find any bugs myself.
To solve this problem, I downloaded my current version of DJGPP (I think the former version was 2.10). This, however, resulted in complete unability  to compile the program. The assembler reports the following line:
z:/djgpp/tmp\cc7Q9EAd.s:4624: Error: Ignoring junk ´F' after expression
>How-To-Repeat:
Start the program.
>Fix:

>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="kvidha.c"
Content-Disposition: inline; filename="kvidha.c"

#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <memory.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <go32.h>
#include <sys\farptr.h>
#include <pc.h>
#include <dpmi.h>

#define NUM_KEYS 9
#define MAX_STACK 16
#define MAX_LINES 100
#define MAX_PIXELS 5000
#define NUM_COLORS 256
#define NUM_PLANES 2
#define NUM_SCRIPTS 4
#define MAX_SPRITES 1000
#define MAX_PLAYERS 16
#define MAX_OBJECTS 1000
#define NUM_WEAPONS 6
#define MAX_HITTESTS 100
#define SHOW_MAP 0

#define MAP_SHOOTABLE 1
#define MAP_WALKABLE 2
#define MAP_DESTROYABLE 4

typedef struct PixelType
{
    float x;
    float y;
    float xv;
    float yv;
    unsigned char c;
    unsigned char SetColor;
    unsigned char Explode;
    signed short Damage;
    unsigned char Owner;
    unsigned char Used;
} Pixel;

typedef struct CacheType
{
    unsigned short w;
    unsigned short h;
    unsigned char NumFrames;
    unsigned char **Frames;
    signed short *cx;
    signed short *cy;
    unsigned char AnimDelay;
} Cache;

typedef struct SpriteType
{
    signed short x;
    signed short y;
    signed char xv;
    signed char yv;
    unsigned char AnimCount;
    unsigned char AnimTimer;
    unsigned char CurFrame;
    unsigned char Template;
    unsigned char Used;
} Sprite;

typedef struct WeaponType
{
    unsigned short Class;
    unsigned short ReloadDelay;
    unsigned short FireDelay;
    unsigned short Ammo;
    unsigned short MaxClips;
    unsigned long Name;
    unsigned short NameLength;
} Weapon;

typedef struct PWeaponType
{
    unsigned short Weapon;
    unsigned short ReloadTimer;
    unsigned short FireTimer;
    unsigned short AmmoLeft;
    unsigned short NumClips;
    signed short Vars[4];
    unsigned char Used;
} PWeapon;

typedef struct PlayerType
{
    unsigned char Visual;
    unsigned short VPointX1;
    unsigned short VPointY1;
    unsigned short VPointX2;
    unsigned short VPointY2;
    unsigned short AMeterX1;
    unsigned short AMeterY1;
    unsigned short AMeterX2;
    unsigned short AMeterY2;
    unsigned short LMeterX1;
    unsigned short LMeterY1;
    unsigned short LMeterX2;
    unsigned short LMeterY2;
    unsigned short lx, ly;
    unsigned short kx, ky;
    unsigned short cx, cy;
    unsigned short Object;
    unsigned short VPObject;
    unsigned char Keys[NUM_KEYS];
    unsigned short KeyCodes[NUM_KEYS];
    unsigned char Left;
    unsigned char Right;
    unsigned char Up;
    unsigned char Down;
    unsigned char Change;
    unsigned char Shoot;
    signed short CurWeapon;
    float Angle;
    float AngleVel;
    unsigned char Dir;
    unsigned char CrossColor;
    signed short Health;
    signed short MaxHealth;
    signed char PVars[40];
    unsigned char Used;
} Player;

typedef struct ClassType
{
    unsigned char *Code;
    unsigned short Scripts[NUM_SCRIPTS];
    unsigned char TickDelay;
    unsigned char Sprite;
    unsigned char StartFrame;
    unsigned char RunHitTests;
    signed short GravityMod;
} Class;

typedef struct ObjectType
{
    float x;
    float y;
    float xv;
    float yv;
    unsigned short Class;
    unsigned char TickTimer;
    signed short Variables[4];
    unsigned short SpriteLink;
    unsigned char Owner;
    unsigned char Used;
} Object;

typedef struct LineType
{
    signed short x1, y1;
    signed short x2, y2;
    unsigned char c1, c2;
    unsigned char Used;
} Line;

typedef struct PalType
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
} Pal;

void SetMapPixel(unsigned short x, unsigned short y, unsigned char c, unsigned short Handle);
unsigned char GetMapPixel(unsigned short x, unsigned short y, unsigned short Handle);
void ShowMap(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned short MapX, unsigned short MapY);
void SetMode(unsigned char Mode);
unsigned char SeekData(char *ID);
unsigned char LoadSprite(char *ID, unsigned short CacheNum);
unsigned short SpawnSprite(unsigned char Template, signed short x, signed short y, signed char xv, signed char yv, unsigned short AnimCount, unsigned char StartFrame);
unsigned char Init(unsigned short *Result);
void Terminate(void);
void SpawnPixel(unsigned short x, unsigned short y, float xv, float yv, unsigned char Owner, unsigned char SetColor, unsigned char Explode, signed short Damage, unsigned char c);
void ControlSprites(void);
void ControlPixels(void);
unsigned char ArgExist(int argc, char *argv[], char *Match);
int main(int argc, char *argv[]);
void CopyToMap(signed short x, signed short y, char *Buffer, unsigned short w, unsigned short h, unsigned char bgc, unsigned char ColorPattern, unsigned char DestroyAll, unsigned short Attributes);
void SpawnExplosion(signed short x, signed short y, unsigned char StartFrame, unsigned char Smokes);
unsigned short SpawnObject(unsigned short Class, unsigned char Owner, unsigned short x, unsigned short y, float xv, float yv);
void ControlObjects(void);
unsigned short WallAngle(unsigned short x, unsigned short y);
void GetInputs(void);
void DBPrint(unsigned char *Buffer, signed short x, signed short y, unsigned char bgc);
unsigned char CollisionTest(signed short *x1, signed short *y1, signed short *x2, signed short *y2, unsigned char Pattern, unsigned char RunHitTests, unsigned short *ObjNum);
void DrawLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned char c1, unsigned char c2);
unsigned short CalcAngle(signed short x1, signed short y1, signed short x2, signed short y2);
void AddHitTest(unsigned short ObjNum);
void RemoveHitTest(unsigned short ObjNum);
void HurtRadius(signed short x, signed short y, signed short StartDamage, signed short StopDamage, unsigned short StartDecRadius, unsigned short StopRadius);
void CollVel(signed short x, signed short y, float *xv, float *yv, unsigned char Attributes);
void MessageBox(unsigned char *Buffer);

Pixel *Pixels[MAX_PIXELS];
Cache **Caches;
Sprite *Sprites[MAX_SPRITES];
Object *Objects[MAX_OBJECTS];
Player *Players[MAX_PLAYERS];
PWeapon *PWeapons[MAX_PLAYERS][NUM_WEAPONS];
Class **Classes;
Weapon **Weapons;
Line *Lines[MAX_LINES];
unsigned short HitTests[MAX_HITTESTS];
unsigned char *Strings;
Pal Palette[NUM_COLORS];
unsigned char ColorInfo[NUM_COLORS];
FILE *DataFile;
float Gravity;
unsigned char *VBuffer = (unsigned char *)0x000A0000;
unsigned char *DblBuffer;
unsigned char *MapBuffer[NUM_PLANES];
signed short clip_x1, clip_x2;
signed short clip_y1, clip_y2;
unsigned char *TempMem;
unsigned short PagesFree;
unsigned short BGSprite, BGFrame;
unsigned short LevelWidth, LevelHeight;
unsigned short MaxLW, MaxLH;
unsigned short NumSprites;
unsigned short NumClasses;
unsigned short NumWeapons;
unsigned char DebugMode;
unsigned short FrameRate;
unsigned short FontSprite;
signed short Regs[32];
unsigned char StackPos;
unsigned short Stack[MAX_STACK];
_go32_dpmi_seginfo OldTimerInt;
_go32_dpmi_seginfo NewTimerIntIret;
_go32_dpmi_seginfo OldKeyInt;
_go32_dpmi_seginfo NewKeyIntIret;
unsigned char raw_key;
unsigned char SpecialKey;
unsigned char ReadyToGo;
unsigned short AsciiTable[256];
float Sine[360], Cosine[360];
unsigned char KeyTable[256];
unsigned short LastShot;
unsigned char *TextBuffer;
unsigned char *KeyboardBuffer;
unsigned char KeybWritePos;
#include "dblbuf.c"
#include "executor.c"

void NewKeyInt()
{
   raw_key = inp(0x60);
    __asm__ (
        "sti\n"
        "in $61, %al\n"
        "or $82, %al\n"
        "out %al, $61\n"
        "and $7F, %al\n"
        "out %al, $61\n"
        "mov $20, %al\n"
        "out %al, $20\n"
    );
    if(raw_key < 128)
    {
        if(SpecialKey == 1)
        {
            KeyTable[raw_key + 128] = 1;
            SpecialKey = 0;
        } else {
            KeyTable[raw_key] = 1;
        }
    } else {
        if(raw_key == 0xE0)
        {
            SpecialKey = 1;
        } else {
            if(SpecialKey == 1)
            {
                KeyTable[raw_key] = 0;
                SpecialKey = 0;
            } else {
                raw_key -= 128;
                KeyTable[raw_key] = 0;
            }
        }
    }
}

void CopyToMap(signed short x, signed short y, char *Buffer, unsigned short w, unsigned short h, unsigned char bgc, unsigned char ColorPattern, unsigned char DestroyAll, unsigned short Attributes)
{
    unsigned short offset;
    unsigned short cx, cy, i;
    unsigned char data;
    unsigned char Colors[NUM_COLORS];
    unsigned char NumColors;

    NumColors = 0;
    for(i = 0; i < NUM_COLORS; i++)
    {
        if(ColorInfo[i] == ColorPattern)
            Colors[NumColors++] = i;
    }
    offset = 0;
    for(cy=0;cy<h;cy++)
    {
        for(cx=0;cx<w;cx++)
        {
            data = Buffer[offset];
            TempMem[offset] = 0;
            if((data != bgc) && (x + cx >= 0) && (x + cx < LevelWidth) && (y + cy >= 0) && (y + cy < LevelHeight))
            {
                if(((GetMapPixel(x + cx, y + cy, 1) & MAP_DESTROYABLE) == MAP_DESTROYABLE) | DestroyAll == 1)
                {
                    if(Attributes != 0xFFFF)
                        SetMapPixel(x + cx, y + cy, (unsigned char)Attributes, 1);
                    TempMem[offset] = 1;
                }
            }
            offset++;
        }
    }
    offset = 0;
    if(ColorPattern == 0)
    {
        for(cy=0;cy<h;cy++)
        {
            for(cx=0;cx<w;cx++)
            {
                data = Buffer[offset];
                if((data != bgc) && (x + cx >= 0) && (x + cx < LevelWidth) && (y + cy >= 0) && (y + cy < LevelHeight))
                {
                    if(TempMem[offset] == 1)
                    {
                        SetMapPixel(x + cx, y + cy, data, 0);
                    }
                }
                offset++;
            }
        }
    } else {
        for(cy=0;cy<h;cy++)
        {
            for(cx=0;cx<w;cx++)
            {
                data = Buffer[offset];
                if((data != bgc) && (x + cx >= 0) && (x + cx < LevelWidth) && (y + cy >= 0) && (y + cy < LevelHeight))
                {
                    if(TempMem[offset] == 1)
                    {
                        SetMapPixel(x + cx, y + cy, Colors[rand() % NumColors], 0);
                    }
                }
                offset++;
            }
        }
    }
}

void ChangeTimer(unsigned short Frequency)
{
    unsigned short SkipCount;

    SkipCount = 1193182 / Frequency;
    outp(0x43, 0x3C);
    outp(0x40, (unsigned char)(SkipCount & 0xFF));
    outp(0x40, (unsigned char)(SkipCount >> 8));
}

void TimerInt(void)
{
    ReadyToGo = 1;
}

void SetMapPixel(unsigned short x, unsigned short y, unsigned char c, unsigned short Handle)
{
    if((x >= LevelWidth) || (y >= LevelHeight))
        return;
    MapBuffer[Handle][x + (y * LevelWidth)] = c;
}

unsigned char GetMapPixel(unsigned short x, unsigned short y, unsigned short Handle)
{
    if((x >= LevelWidth) || (y >= LevelHeight))
        return(0);
    return(MapBuffer[Handle][x + (y * LevelWidth)]);
}

void ShowMap(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned short MapX, unsigned short MapY)
{
    unsigned short Window;
    unsigned short cwx, cwy;
    signed short x, y;
    unsigned short i;
    unsigned short CurFrame;
    unsigned char Template;

    if((MapX >= LevelWidth) || (MapY >= LevelHeight)) return;
    DBSetClip(x1, y1, x2, y2);
    cwx = (MapX / 2) % Caches[BGSprite]->w;
    cwy = (MapY / 2) % Caches[BGSprite]->h;
    for(y = (signed short)(y1 - Caches[BGSprite]->h); y <= (signed short)y2; y += Caches[BGSprite]->h)
    {
        for(x = (signed short)(x1 - Caches[BGSprite]->w); x <= (signed short)x2; x += Caches[BGSprite]->w)
        {
            DBCopyBufferClip((signed short)x - cwx, (signed short)y - cwy, Caches[BGSprite]->Frames[BGFrame], Caches[BGSprite]->w, Caches[BGSprite]->h, -1);
        }
    }
    DBCopyBufferClip((signed short)x1 - (signed short)MapX, (signed short)y1 - (signed short)MapY, MapBuffer[0], LevelWidth, LevelHeight, 0);
    for(i = 0; i < MAX_LINES; i++)
    {
        if(Lines[i]->Used == 1)
            DBLine(Lines[i]->x1 - MapX + x1, Lines[i]->y1 - MapY + y1, Lines[i]->x2 - MapX + x1, Lines[i]->y2 - MapY + y1, Lines[i]->c1, Lines[i]->c2);
    }
    for(i = 0; i < MAX_PIXELS; i++)
    {
        if(Pixels[i]->Used == 1)
            DBPSetC((unsigned short)(Pixels[i]->x - MapX + x1), (unsigned short)(Pixels[i]->y - MapY + y1), Pixels[i]->c);
    }
    for(i = 0; i < MAX_SPRITES; i++)
    {
        if(Sprites[i]->Used == 1)
        {
            CurFrame = Sprites[i]->CurFrame;
            Template = Sprites[i]->Template;
            DBCopyBufferClip((signed short)(Sprites[i]->x - MapX - Caches[Template]->cx[CurFrame] + x1), (signed short)(Sprites[i]->y - MapY - Caches[Template]->cy[CurFrame] + y1), Caches[Template]->Frames[CurFrame], Caches[Template]->w, Caches[Template]->h, 0);
        }
    }
    DBSetClip(0, 0, 319, 199);
}

void DrawScreen(void)
{
    unsigned short i, x, y, x2, y2;
    unsigned short cx, cy;
    signed short tx, ty, CurWeapon;
    float Per;

    DBFRect(0, 0, 319, 199, 0);
    for(i = 0; i < MAX_PLAYERS; i++)
    {
        if(Players[i]->Visual == 1)
        {
            x = Objects[Players[i]->VPObject]->x;
            y = Objects[Players[i]->VPObject]->y;
            cx = (Players[i]->VPointX2 - Players[i]->VPointX1) >> 1;
            cy = (Players[i]->VPointY2 - Players[i]->VPointY1) >> 1;
            if(x < cx) x = cx;
            if(y < cy) y = cy;
            if(x > LevelWidth - cx - 2)
                x = LevelWidth - cx - 2;
            if(y > LevelHeight - cy - 2)
                y = LevelHeight - cy - 2;
            ShowMap(Players[i]->VPointX1, Players[i]->VPointY1, Players[i]->VPointX2, Players[i]->VPointY2, x - cx, y - cy);
            DBSetClip(Players[i]->VPointX1, Players[i]->VPointY1, Players[i]->VPointX2, Players[i]->VPointY2);
            x2 = (unsigned short)((unsigned short)(Objects[Players[i]->Object]->x) + (Cosine[(unsigned short)Players[i]->Angle] * ((Players[i]->Dir == 0)?15:-15)) - x + cx + Players[i]->VPointX1 + ((Players[i]->Dir == 0)?3:-2));
            y2 = (unsigned short)((unsigned short)(Objects[Players[i]->Object]->y) - (Sine[(unsigned short)Players[i]->Angle] * 15) - y + cy + Players[i]->VPointY1 - 2);
            DBPSetC(x2 - 1, y2, Players[i]->CrossColor);
            DBPSetC(x2 + 1, y2, Players[i]->CrossColor);
            DBPSetC(x2, y2 - 1, Players[i]->CrossColor);
            DBPSetC(x2, y2 + 1, Players[i]->CrossColor);
            if(Players[i]->Change)
            {
                tx = (signed short)(Objects[Players[i]->Object]->x - x + cx + Players[i]->VPointX1 - (Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->NameLength * 2));
                ty = (signed short)(Objects[Players[i]->Object]->y - y + cy + Players[i]->VPointY1 - 20);
                DBPrint((unsigned char *)&Strings[Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->Name], tx, ty, 0);
            }
            DBSetClip(0, 0, 319, 199);
            CurWeapon = Players[i]->CurWeapon;
            if(PWeapons[i][CurWeapon]->ReloadTimer == 0)
            {
                Per = (float)PWeapons[i][Players[i]->CurWeapon]->AmmoLeft / (float)Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->Ammo;
            } else {
                Per = (float)PWeapons[i][CurWeapon]->ReloadTimer / (float)Weapons[PWeapons[i][CurWeapon]->Weapon]->ReloadDelay;
            }
            DBFRect(Players[i]->AMeterX1, Players[i]->AMeterY1, Players[i]->AMeterX1 + (signed short)(Per * (Players[i]->AMeterX2 - Players[i]->AMeterX1)), Players[i]->AMeterY2, 48 + (unsigned char)(Per * 7));
            Per = (float)Players[i]->Health / (float)Players[i]->MaxHealth;
            DBFRect(Players[i]->LMeterX1, Players[i]->LMeterY1, Players[i]->LMeterX1 + (signed short)(Per * (Players[i]->LMeterX2 - Players[i]->LMeterX1)), Players[i]->LMeterY2, 40 + (unsigned char)(Per * 7));
        }
    }
    if(SHOW_MAP == 1)
    {
        for(y = 0; y < 40; y++)
        {
            for(x = 0; x < 64; x++)
            {
                DBPSetC(128 + x, 160 + y, GetMapPixel(x * (LevelWidth * 5), y * (LevelHeight * 5), 0));
            }
        }
        for(i = 0; i < MAX_PLAYERS; i++)
        {
            if(Players[i]->Used == 1)
            {
                DBPSetC(128 + (unsigned short)(Objects[Players[i]->Object]->x / (LevelWidth * 5)), 160 + (unsigned short)(Objects[Players[i]->Object]->y / (LevelHeight * 5)), 6);
            }
        }
    }
}

unsigned short CalcAngle(signed short x1, signed short y1, signed short x2, signed short y2)
{
    double a;
    unsigned char Q;

    if(x1 == x2)
    {
        if(y1 >= y2)
          return(90);
        if(y1 < y2)
          return(270);
    }
    a = atan((double)(y1 - y2) / (double)(x1 - x2));
    if(a < 0)
        a = -a;
    if((y1 >= y2) && (x1 < x2))
        Q = 0;
    if((y1 >= y2) && (x1 >= x2))
    {
        Q = 1;
        a = 1.570796 - a;
    }
    if((y1 < y2) && (x1 >= x2))
        Q = 2;
    if((y1 < y2) && (x1 < x2))
    {
        Q = 3;
        a = 1.570796 - a;
    }
    return((unsigned short)(((a + (Q * 1.570796)) / 3.141593) * 180));
}

void GetInputs(void)
{
    static Row = 1;
    unsigned char i, o;

    for(i = 0; i < MAX_PLAYERS; i++)
    {
        for(o = 0; o < NUM_KEYS; o++)
        {
            if(((Players[i]->KeyCodes[o] & 0xFF00) == 0)?(KeyTable[Players[i]->KeyCodes[o]] == 1):((KeyTable[(Players[i]->KeyCodes[o] & 0xFF00) >> 8] == 1) && (KeyTable[Players[i]->KeyCodes[o] & 0x00FF] == 1)))
            {
                if(Players[i]->Keys[o] == 0)
                {
                    Players[i]->Keys[o] = 1;
                } else {
                    Players[i]->Keys[o] = 2;
                }
            } else {
                Players[i]->Keys[o] = 0;
            }
        }
    }
}

void SetMode(unsigned char Mode)
{
    union REGS Regs;

    Regs.h.ah = 0;
    Regs.h.al = Mode;
    _int86(0x10, &Regs, &Regs);
}

void MessageBox(unsigned char *Buffer)
{
    DBFRect(68, 88, 252, 112, 40);
    DBFRect(69, 89, 251, 111, 0);
    DBPrint(Buffer, 70, 90, 255);
    DisplayDB();
    while(KeyTable[57] == 1);
    while(KeyTable[57] == 0);
}

unsigned char SeekData(char *ID)
{
    unsigned long offset;
    unsigned long endoffset;
    unsigned long i;
    unsigned char BufferOffset;
    unsigned short Pointer;
    char InpBuffer;
    char Buffer[80];

    fseek(DataFile, 0, SEEK_SET);
    fread((void *)&offset, 4, 1, DataFile);
    fread((void *)&endoffset, 4, 1, DataFile);
    fseek(DataFile, offset, SEEK_SET);
    BufferOffset = 0;
    Pointer = 0;
    for(i = 0; i < endoffset - offset; i++)
    {
        fread((void *)&InpBuffer, 1, 1, DataFile);
        Buffer[BufferOffset++] = InpBuffer;
        if(InpBuffer == 0)
        {
            Pointer++;
            BufferOffset = 0;
            if(strcmp(ID, (char *)Buffer) == 0)
            {
                fseek(DataFile, Pointer * 4, SEEK_SET);
                fread((void *)&offset, 4, 1, DataFile);
                fseek(DataFile, offset, SEEK_SET);
                return(1);
            }
        }
    }
    return(0);
}

unsigned char LoadSprite(char *ID, unsigned short CacheNum)
{
    unsigned short i, o, Found;

    if(SeekData(ID) == 0)
        return(1);
    fread((void *)&Caches[CacheNum]->w, 2, 1, DataFile);
    fread((void *)&Caches[CacheNum]->h, 2, 1, DataFile);
    fread((void *)&Caches[CacheNum]->NumFrames, 1, 1, DataFile);
    fread((void *)&Caches[CacheNum]->AnimDelay, 1, 1, DataFile);
    if((Caches[CacheNum]->cx = (signed short *)malloc(Caches[CacheNum]->NumFrames * 2)) == NULL)
        return(2);
    if((Caches[CacheNum]->cy = (signed short *)malloc(Caches[CacheNum]->NumFrames * 2)) == NULL)
        return(2);
    if((Caches[CacheNum]->Frames = (unsigned char **)malloc(Caches[CacheNum]->NumFrames * 4)) == NULL)
        return(2);
    for(o = 0; o < Caches[CacheNum]->NumFrames; o++)
    {
        fread((void *)&Caches[CacheNum]->cx[o], 2, 1, DataFile);
        fread((void *)&Caches[CacheNum]->cy[o], 2, 1, DataFile);
        if((Caches[CacheNum]->Frames[o] = (unsigned char *)malloc(Caches[CacheNum]->w * Caches[CacheNum]->h)) == NULL)
            return(2);
        fread((void *)Caches[CacheNum]->Frames[o], Caches[CacheNum]->w * Caches[CacheNum]->h, 1, DataFile);
    }
    return(0);
}

unsigned short SpawnSprite(unsigned char Template, signed short x, signed short y, signed char xv, signed char yv, unsigned short AnimCount, unsigned char StartFrame)
{
    unsigned short i, o, Found;

    Found = 0;
    for(i = 0; i < MAX_SPRITES; i++)
    {
        if(Sprites[i]->Used == 0)
        {
            Found = 1;
            Sprites[i]->x = x;
            Sprites[i]->y = y;
            Sprites[i]->xv = xv;
            Sprites[i]->yv = yv;
            Sprites[i]->AnimTimer = 0;
            Sprites[i]->AnimCount = AnimCount;
            Sprites[i]->CurFrame = StartFrame;
            Sprites[i]->Template = Template;
            Sprites[i]->Used = 1;
            break;
        }
    }
    return((Found == 0)?0xFFFF:i);
}

unsigned long GetString(unsigned short StringNum, unsigned short *Length)
{
    unsigned long Offset, Offset2;
    unsigned short Count;

    Offset = 0;
    Count = 0;
    while(Count < StringNum)
    {
        if(Strings[Offset++] == 0)
            Count++;
    }
    Offset2 = Offset;
    while(Strings[Offset2++] != 0);
    if(Length != NULL)
        *Length = Offset2 - Offset;
    return(Offset);
}

void LoadLayout(unsigned char NumPlayers)
{
    unsigned char i;
    unsigned short Buffer[18];

    SeekData("Layouts");
    for(i = 0; i < NumPlayers - 1; i++)
    {
        fseek(DataFile, 36 * (i + 1), SEEK_CUR);
    }
    for(i = 0; i < NumPlayers; i++)
    {
        fread((void *)&Buffer, 2, 18, DataFile);
        Players[i]->VPointX1 = Buffer[0];
        Players[i]->VPointY1 = Buffer[1];
        Players[i]->VPointX2 = Buffer[2];
        Players[i]->VPointY2 = Buffer[3];
        Players[i]->AMeterX1 = Buffer[4];
        Players[i]->AMeterY1 = Buffer[5];
        Players[i]->AMeterX2 = Buffer[6];
        Players[i]->AMeterY2 = Buffer[7];
        Players[i]->LMeterX1 = Buffer[8];
        Players[i]->LMeterY1 = Buffer[9];
        Players[i]->LMeterX2 = Buffer[10];
        Players[i]->LMeterY2 = Buffer[11];
        Players[i]->lx = Buffer[12];
        Players[i]->ly = Buffer[13];
        Players[i]->kx = Buffer[14];
        Players[i]->ky = Buffer[15];
        Players[i]->cx = Buffer[16];
        Players[i]->cy = Buffer[17];
    }
}

void InitVar(void)
{
    unsigned short i, o;

    Players[0]->KeyCodes[0] = 203;                              //Left:        Left Arrow
    Players[0]->KeyCodes[1] = 205;                              //Right:       Right Arrow
    Players[0]->KeyCodes[2] = 200;                              //Up:          Up Arrow
    Players[0]->KeyCodes[3] = 208;                              //Down:        Down Arrow
    Players[0]->KeyCodes[4] = 157;                              //Shoot:       Right Ctrl
    Players[0]->KeyCodes[5] = 54;                               //Change:      Right Shift
    Players[0]->KeyCodes[6] = 28;                               //Jump:        Enter
    Players[0]->KeyCodes[7] = (54 << 8) + 28;                   //Ninja Rope:  Right Shift + Enter
    Players[0]->KeyCodes[8] = (54 << 8) + 157;                  //Trigger:     Right Shift + Right Ctrl
    Players[1]->KeyCodes[0] = 33;                               //Left:        F
    Players[1]->KeyCodes[1] = 35;                               //Right:       H
    Players[1]->KeyCodes[2] = 20;                               //Up:          T
    Players[1]->KeyCodes[3] = 34;                               //Down:        G
    Players[1]->KeyCodes[4] = 4;                                //Shoot:       3
    Players[1]->KeyCodes[5] = 3;                                //Change:      2
    Players[1]->KeyCodes[6] = 2;                                //Jump:        1
    Players[1]->KeyCodes[7] = (3 << 8) + 2;                     //Ninja Rope:  2 + 1
    Players[1]->KeyCodes[8] = (3 << 8) + 4;                     //Trigger:     2 + 3
    Players[0]->Visual = 1;
    Players[1]->Visual = 1;
    Players[0]->Angle = 0;
    Players[0]->AngleVel = 0;
    Players[0]->Dir = 0;
    Players[0]->MaxHealth = 100;
    Players[0]->Health = Players[0]->MaxHealth;
    Players[1]->Angle = 0;
    Players[1]->AngleVel = 0;
    Players[1]->Dir = 0;
    Players[1]->MaxHealth = 100;
    Players[1]->Health = Players[1]->MaxHealth;
    LoadLayout(2);
    for(i = 0; i < 2; i++)
    {
        for(o = 0; o < 6; o++)
        {
            PWeapons[i][o]->Weapon = o;
            PWeapons[i][o]->Used = 1;
        }
    }
    Players[0]->CurWeapon = 4;
    Players[1]->CurWeapon = 1;
    for(i = 0; i < MAX_PLAYERS; i++)
    {
        for(o = 0; o < NUM_WEAPONS; o++)
        {
            if((Players[i]->Used == 1) && (PWeapons[i][o]->Used == 1))
            {
                PWeapons[i][o]->AmmoLeft = Weapons[PWeapons[i][o]->Weapon]->Ammo;
                PWeapons[i][o]->FireTimer = 0;
                PWeapons[i][o]->ReloadTimer = 0;
                PWeapons[i][o]->NumClips = Weapons[PWeapons[i][o]->Weapon]->MaxClips;
            }
        }
    }
    BGSprite = 10;
    BGFrame = 0;
}

unsigned char Init(unsigned short *Result)
{
    unsigned short Segment, Total;
    unsigned short i, o;
    unsigned char Buffer[80], InpBuffer, BufferPos, Finished;
    unsigned long LastPos, Offset;
    unsigned short DataLength, Count;

    printf("Initializing...\n");
    if((DataFile = fopen("KVID.DAT", "rb")) == NULL)
        return(3);
    if(DebugMode != 0)
        printf("Initializing double buffer...\n");
    if((DblBuffer = (unsigned char *)malloc(64000)) == NULL)
        return(2);
    if((TempMem = (unsigned char *)malloc(64000)) == NULL)
        return(2);
    for(i=0;i<64000;i++)
    {
        DblBuffer[i] = 0;
    }
    DBSetClip(0, 0, 319, 199);
    if(DebugMode != 0)
        printf("Initializing level...\n");
    MaxLW = 10;
    MaxLH = 10;
    for(i = 0; i < NUM_PLANES; i++)
    {
        if((MapBuffer[i] = (unsigned char *)malloc(MaxLW * MaxLH * 64000)) == NULL)
            return(5);
    }
    if(DebugMode != 0)
        printf("Initializing variables...\n");
    for(i = 0; i < MAX_HITTESTS; i++)
    {
        HitTests[i] = 0xFFFF;
    }
    for(i = 0; i < MAX_PIXELS; i++)
    {
        if((Pixels[i] = (Pixel *)malloc(sizeof(Pixel))) == NULL)
            return(2);
        Pixels[i]->Used = 0;
    }
    for(i = 0; i < MAX_SPRITES; i++)
    {
        if((Sprites[i] = (Sprite *)malloc(sizeof(Sprite))) == NULL)
            return(2);
        Sprites[i]->Used = 0;
    }
    for(i = 0; i < MAX_OBJECTS; i++)
    {
        if((Objects[i] = (Object *)malloc(sizeof(Object))) == NULL)
            return(2);
        Objects[i]->Used = 0;
    }
    for(i = 0; i < MAX_PLAYERS; i++)
    {
        if((Players[i] = (Player *)malloc(sizeof(Player))) == NULL)
            return(2);
        Players[i]->Used = 0;
        Players[i]->Visual = 0;
    }
    for(i = 0; i < MAX_PLAYERS; i++)
    {
        for(o = 0; o < NUM_WEAPONS; o++)
        {
            if((PWeapons[i][o] = (PWeapon *)malloc(sizeof(PWeapon))) == NULL)
                return(2);
            PWeapons[i][o]->Used = 0;
        }
    }
    for(i = 0; i < MAX_LINES; i++)
    {
        if((Lines[i] = (Line *)malloc(sizeof(Line))) == NULL)
            return(2);
        Lines[i]->Used = 0;
    }
    if((TextBuffer = (unsigned char *)malloc(500)) == NULL)
        return(2);
    if((KeyboardBuffer = (unsigned char *)malloc(500)) == NULL)
        return(2);
    Gravity = 0.02;
    LevelWidth = 320 * 2;
    LevelHeight = 200 * 2;
    FrameRate = 500;
    srand((unsigned int)time(NULL));
    for(i = 0; i < 360; i++)
    {
        Sine[i] = sin(((float)i / 180) * 3.141593);
        Cosine[i] = cos(((float)i / 180) * 3.141593);
    }
    if(DebugMode != 0)
        printf("Loading data...\n");
    if(SeekData("Layouts") == 0)
        return(4);
    if(SeekData("DefaultPalette") == 0)
        return(4);
    fread((void *)Palette, sizeof(Pal), NUM_COLORS, DataFile);
    if(SeekData("ColorInfo") == 0)
        return(4);
    fread((void *)ColorInfo, 1, NUM_COLORS, DataFile);
    if(SeekData("AsciiConv") == 0)
        return(4);
    fread((void *)AsciiTable, 2, 256, DataFile);
    if(SeekData("Strings") == 0)
        return(4);
    fread((void *)&LastPos, 4, 1, DataFile);
    if((Strings = (unsigned char *)malloc((unsigned short)LastPos)) == NULL)
        return(2);
    for(Offset = 0; Offset < LastPos; Offset++)
    {
        fread((void *)&InpBuffer, 1, 1, DataFile);
        Strings[Offset] = InpBuffer;
    }
    if(SeekData("SpriteCache") == 0)
        return(4);
    fread((void *)&NumSprites, 2, 1, DataFile);
    if((Caches = (Cache **)malloc(4 * NumSprites)) == NULL)
        return(2);
    for(i = 0; i < NumSprites; i++)
    {
        if((Caches[i] = (Cache *)malloc(sizeof(Cache))) == NULL)
            return(2);
        BufferPos = 0;
        Finished = 0;
        while(Finished == 0)
        {
            fread((void *)&InpBuffer, 1, 1, DataFile);
            if(InpBuffer == 0)
            {
                Buffer[BufferPos] = 0;
                LastPos = ftell(DataFile);
                switch(LoadSprite((char *)Buffer, i))
                {
                    case 1:
                        return(4);
                    case 2:
                        return(2);
                }
                if(strcmp((char *)Buffer, (char *)"Spr_Font") == 0)
                    FontSprite = i;
                fseek(DataFile, LastPos, SEEK_SET);
                Finished = 1;
            } else
            {
                Buffer[BufferPos++] = InpBuffer;
            }
        }
    }
    if(SeekData("Classes") == 0)
        return(4);
    fread((void *)&NumClasses, 2, 1, DataFile);
    if((Classes = (Class **)malloc(4 * NumClasses)) == NULL)
        return(2);
    for(i = 0; i < NumClasses; i++)
    {
        if((Classes[i] = (Class *)malloc(sizeof(Class))) == NULL)
            return(2);
        fread((void *)&Classes[i]->Scripts, 2, NUM_SCRIPTS, DataFile);
        fread((void *)&Classes[i]->TickDelay, 1, 1, DataFile);
        fread((void *)&Classes[i]->GravityMod, 2, 1, DataFile);
        fread((void *)&Classes[i]->Sprite, 1, 1, DataFile);
        fread((void *)&Classes[i]->StartFrame, 1, 1, DataFile);
        fread((void *)&Classes[i]->RunHitTests, 1, 1, DataFile);
        fread((void *)&DataLength, 2, 1, DataFile);
        if((Classes[i]->Code = (unsigned char *)malloc(DataLength)) == NULL)
            return(2);
        fread((void *)Classes[i]->Code, 1, DataLength, DataFile);
    }
    if(SeekData("WeaponInfo") == 0)
        return(4);
    fread((void *)&NumWeapons, 2, 1, DataFile);
    if((Weapons = (Weapon **)malloc(4 * NumWeapons)) == NULL)
        return(2);
    for(i = 0; i < NumWeapons; i++)
    {
        if((Weapons[i] = (Weapon *)malloc(sizeof(Weapon))) == NULL)
            return(2);
        fread((void *)&Weapons[i]->Class, 2, 1, DataFile);
        fread((void *)&Weapons[i]->ReloadDelay, 2, 1, DataFile);
        fread((void *)&Weapons[i]->FireDelay, 2, 1, DataFile);
        fread((void *)&Weapons[i]->Ammo, 2, 1, DataFile);
        Weapons[i]->Name = 0;
        fread((void *)&Weapons[i]->MaxClips, 2, 1, DataFile);
        fread((void *)&Weapons[i]->Name, 2, 1, DataFile);
        Weapons[i]->Name = GetString((unsigned short)Weapons[i]->Name, (unsigned short *)&Weapons[i]->NameLength);
    }
    if(DebugMode != 0)
        printf("Initializing hardware...\n");
    ChangeTimer(FrameRate);
    printf("Done!\n");
    getch();
    _go32_dpmi_get_protected_mode_interrupt_vector(0x1C, &OldTimerInt);
    _go32_dpmi_get_protected_mode_interrupt_vector(0x09, &OldKeyInt);
    SetMode(0x13);
    NewTimerIntIret.pm_offset = (unsigned long)TimerInt;
    NewTimerIntIret.pm_selector = _go32_my_cs();
    _go32_dpmi_allocate_iret_wrapper(&NewTimerIntIret);
    _go32_dpmi_set_protected_mode_interrupt_vector(0x1C, &NewTimerIntIret);
    NewKeyIntIret.pm_offset = (unsigned long)NewKeyInt;
    NewKeyIntIret.pm_selector = _go32_my_cs();
    _go32_dpmi_allocate_iret_wrapper(&NewKeyIntIret);
    _go32_dpmi_set_protected_mode_interrupt_vector(0x09, &NewKeyIntIret);
    for(i = 0; i < NUM_COLORS; i++)
    {
        outp(0x3c8, i);
        outp(0x3c9, Palette[i].r);
        outp(0x3c9, Palette[i].g);
        outp(0x3c9, Palette[i].b);
    }
    return(0xFF);
}

void Terminate(void)
{
    unsigned short i, o;

    SetMode(0x03);
    free(DblBuffer);
    free(TempMem);
    fclose(DataFile);
    for(i = 0; i < NUM_PLANES; i++)
    {
        if(MapBuffer[i] != NULL)
            free(MapBuffer[i]);
    }
    _go32_dpmi_set_protected_mode_interrupt_vector(0x09, &OldKeyInt);
    _go32_dpmi_set_protected_mode_interrupt_vector(0x1C, &OldTimerInt);
    _go32_dpmi_free_iret_wrapper(&NewKeyIntIret);
    _go32_dpmi_free_iret_wrapper(&NewTimerIntIret);
    outp(0x43, 0x3C);
    outp(0x40, 0xFF);
    outp(0x40, 0xFF);
    for(i = 0; i < MAX_PIXELS; i++)
    {
        if(Pixels[i] != NULL)
            free(Pixels[i]);
    }
    for(i = 0; i < NumSprites; i++)
    {
        if(Caches[i] != NULL)
        {
            if(Caches[i]->cx != NULL)
                free(Caches[i]->cx);
            if(Caches[i]->cy != NULL)
                free(Caches[i]->cy);
            if(Caches[i]->Frames != NULL)
            {
                for(o = 0; o < Caches[i]->NumFrames; o++)
                {
                    if(Caches[i]->Frames[o] != NULL)
                        free(Caches[i]->Frames[o]);
                }
                free(Caches[i]->Frames);
            }
            free(Caches[i]);
        }
    }
    if(Caches != NULL)
        free(Caches);
    for(i = 0; i < MAX_SPRITES; i++)
    {
        if(Sprites[i] != NULL)
            free(Sprites[i]);
    }
    for(i = 0; i < MAX_PLAYERS; i++)
    {
        if(Players[i] != NULL)
            free(Players[i]);
    }
    for(i = 0; i < MAX_OBJECTS; i++)
    {
        if(Objects[i] != NULL)
            free(Objects[i]);
    }
    for(i = 0; i < NumClasses; i++)
    {
        if(Classes[i]->Code != NULL)
            free(Classes[i]->Code);
        if(Classes[i] != NULL)
            free(Classes[i]);
    }
    if(Classes != NULL)
        free(Classes);
    for(i = 0; i < NumWeapons; i++)
    {
        if(Weapons[i] != NULL)
            free(Weapons[i]);
    }
    if(Weapons != NULL)
        free(Weapons);
    for(i = 0; i < MAX_PLAYERS; i++)
    {
        for(o = 0; o < NUM_WEAPONS; o++)
        {
            if(PWeapons[i][o] != NULL)
                free(PWeapons[i][o]);
        }
    }
    for(i = 0; i < MAX_LINES; i++)
    {
        if(Lines[i] != NULL)
            free(Lines[i]);
    }
    if(Strings != NULL)
        free(Strings);
    if(TextBuffer != NULL)
        free(TextBuffer);
    if(KeyboardBuffer != NULL)
        free(KeyboardBuffer);
}

void HurtRadius(signed short x, signed short y, signed short StartDamage, signed short StopDamage, unsigned short StartDecRadius, unsigned short StopRadius)
{
    unsigned short i;
    signed long square, xdist, ydist;
    unsigned short Radius;
    signed short Damage;

    for(i = 0; i < MAX_OBJECTS; i++)
    {
        if(Objects[i]->Used == 1)
        {
            xdist = (unsigned long)(x - (signed short)Objects[i]->x);
            ydist = (unsigned long)(y - (signed short)Objects[i]->y);
            square = (xdist * xdist) + (ydist * ydist);
            Radius = (unsigned short)sqrt((double)square);
            if(Radius < StopRadius)
            {
                if(Radius < StartDecRadius)
                {
                    Damage = StartDamage;
                } else {
                    Damage = (unsigned short)(((float)((StopRadius - StartDecRadius) - (Radius - StartDecRadius)) / (float)(StopRadius - StartDecRadius)) * (float)Damage);
                }
                Regs[16] = (signed short)i;
                Regs[17] = (signed short)Damage;
                Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Objects[i]->Class]->Scripts[3]);                        //TakeDamage
            }
        }
    }
}

unsigned char CollisionTest(signed short *x1, signed short *y1, signed short *x2, signed short *y2, unsigned char Pattern, unsigned char RunHitTests, unsigned short *ObjNum)
{
    signed short dx, dy, x, y, fx, fy;
    signed short xi, yi, d;
    unsigned short i, o, SpriteLink, Template;
    unsigned long Offset;
    unsigned char Data;
    unsigned char *FrameBuffer;

    dx = *x2 - *x1;
    dy = *y2 - *y1;
    if(dx >= 0)
    {
        xi = 1;
    } else {
        xi = -1;
        dx = -dx;
    }
    if(dy >= 0)
    {
        yi = 1;
    } else {
        yi = -1;
        dy = -dy;
    }
    d = 0;
    x = *x1;
    y = *y1;
    if(dx > dy)
    {
        for(i = 0; i <= dx; i++)
        {
            if(i > 0)
            {
                Data = GetMapPixel((unsigned short)x, (unsigned short)y, 1);
                if((Data & Pattern) == 0)
                {
                    *x1 = fx;
                    *y1 = fy;
                    *x2 = x;
                    *y2 = y;
                    return(1);
                }
                if(RunHitTests == 1)
                {
                    for(o = 0; o < MAX_HITTESTS; o++)
                    {
                        if(HitTests[o] == 0xFFFF)
                            break;
                        SpriteLink = Objects[HitTests[o]]->SpriteLink;
                        if(SpriteLink != 0xFFFF)
                        {
                            Template = Sprites[SpriteLink]->Template;
                            if((x >= Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame]) && (y >= Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) && (x < Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame] + Caches[Template]->w) && (y < Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame] + Caches[Template]->h))
                            {
                                Offset = x - Sprites[SpriteLink]->x + Caches[Template]->cx[Sprites[SpriteLink]->CurFrame];
                                Offset += (y - Sprites[SpriteLink]->y + Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) * Caches[Template]->w;
                                FrameBuffer = Caches[Template]->Frames[Sprites[SpriteLink]->CurFrame];
                                if(FrameBuffer[Offset] != 0)
                                {
                                    *x1 = fx;
                                    *y1 = fy;
                                    *x2 = x;
                                    *y2 = y;
                                    *ObjNum = HitTests[o];
                                    return(2);
                                }
                            }
                        }
                    }
                }
            }
            fx = x;
            fy = y;
            d += dy;
            if(d > dx)
            {
                d -= dx;
                y += yi;
            }
            x += xi;
        }
    } else {
        for(i = 0; i <= dy; i++)
        {
            if(i > 0)
            {
                Data = GetMapPixel((unsigned short)x, (unsigned short)y, 1);
                if((Data & Pattern) == 0)
                {
                    *x1 = fx;
                    *y1 = fy;
                    *x2 = x;
                    *y2 = y;
                    return(1);
                }
                if(RunHitTests == 1)
                {
                    for(o = 0; o < MAX_HITTESTS; o++)
                    {
                        if(HitTests[o] == 0xFFFF)
                            break;
                        SpriteLink = Objects[HitTests[o]]->SpriteLink;
                        if(SpriteLink != 0xFFFF)
                        {
                            Template = Sprites[SpriteLink]->Template;
                            if((x >= Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame]) && (y >= Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) && (x < Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame] + Caches[Template]->w) && (y < Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame] + Caches[Template]->h))
                            {
                                Offset = x - Sprites[SpriteLink]->x + Caches[Template]->cx[Sprites[SpriteLink]->CurFrame];
                                Offset += (y - Sprites[SpriteLink]->y + Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) * Caches[Template]->w;
                                FrameBuffer = Caches[Template]->Frames[Sprites[SpriteLink]->CurFrame];
                                if(FrameBuffer[Offset] != 0)
                                {
                                    *x1 = fx;
                                    *y1 = fy;
                                    *x2 = x;
                                    *y2 = y;
                                    *ObjNum = HitTests[o];
                                    return(2);
                                }
                            }
                        }
                    }
                }
            }
            fx = x;
            fy = y;
            d += dx;
            if(d > 0)
            {
                d -= dy;
                x += xi;
            }
            y += yi;
        }
    }
    return(0);
}

void AddHitTest(unsigned short ObjNum)
{
    unsigned short i;

    for(i = 0; i < MAX_HITTESTS; i++)
    {
        if(HitTests[i] == 0xFFFF)
        {
            HitTests[i] = ObjNum;
            return;
        }
    }
}

void RemoveHitTest(unsigned short ObjNum)
{
    unsigned short i;

    for(i = 0; i < MAX_HITTESTS; i++)
    {
        if(HitTests[i] == ObjNum)
        {
            for(i = i; i < MAX_HITTESTS; i++)
                HitTests[i] = HitTests[i + 1];
            HitTests[MAX_HITTESTS - 1] = 0xFFFF;
            break;
        }
    }
}

void DBPrint(unsigned char *Buffer, signed short sx, signed short y, unsigned char bgc)
{
    unsigned long Offset;
    unsigned char CurChar;
    signed short x;

    Offset = 0;
    x = sx;
    while((CurChar = Buffer[Offset++]) != 0)
    {
        switch(CurChar)
        {
            case 10:
              y += 5;
              break;
            case 13:
              x = sx;
              break;
            default:
                if(AsciiTable[CurChar] != 65535)
                {
                    DBCopyBufferClip(x, y, Caches[FontSprite]->Frames[AsciiTable[CurChar]], Caches[FontSprite]->w, Caches[FontSprite]->h, bgc);
                } else {
                    if(bgc != 0)
                        DBFRect(x, y, x + 2, y + 3, 0);
                }
                x += Caches[FontSprite]->w + 1;
                break;
        }
    }
}

unsigned short WallAngle(unsigned short x, unsigned short y)
{
   return(0);
}

void SpawnPixel(unsigned short x, unsigned short y, float xv, float yv, unsigned char Owner, unsigned char SetColor, unsigned char Explode, signed short Damage, unsigned char c)
{
    unsigned short i;

    for(i = 0; i < MAX_PIXELS; i++)
    {
        if(Pixels[i]->Used == 0)
        {
            Pixels[i]->x = x;
            Pixels[i]->y = y;
            Pixels[i]->xv = xv;
            Pixels[i]->yv = yv;
            Pixels[i]->c = c;
            Pixels[i]->SetColor = SetColor;
            Pixels[i]->Explode = Explode;
            Pixels[i]->Damage = Damage;
            Pixels[i]->Owner = Owner;
            Pixels[i]->Used = 1;
            return;
        }
    }
}


void DrawLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned char c1, unsigned char c2)
{
    unsigned short i;

    for(i = 0; i < MAX_LINES; i++)
    {
        if(Lines[i]->Used == 0)
        {
            Lines[i]->x1 = x1;
            Lines[i]->y1 = y1;
            Lines[i]->x2 = x2;
            Lines[i]->y2 = y2;
            Lines[i]->c1 = c1;
            Lines[i]->c2 = c2;
            Lines[i]->Used = 1;
            return;
        }
    }
}

unsigned short SpawnObject(unsigned short Class, unsigned char Owner, unsigned short x, unsigned short y, float xv, float yv)
{
    unsigned short i, o;

    for(i = 0; i < MAX_OBJECTS; i++)
    {
        if(Objects[i]->Used == 0)
        {
            Objects[i]->x = (float)x;
            Objects[i]->y = (float)y;
            Objects[i]->xv = xv;
            Objects[i]->yv = yv;
            Objects[i]->Class = Class;
            Objects[i]->Owner = Owner;
            Objects[i]->TickTimer = 0;
            Objects[i]->SpriteLink = (Classes[Class]->Sprite != 0xFF)?(SpawnSprite(Classes[Class]->Sprite, (signed short)x, (signed short)y, 0, 0, 0, Classes[Class]->StartFrame)):0xFFFF;
            Objects[i]->Used = 1;
            Regs[16] = i;
            Regs[17] = (signed short)Objects[i]->x;
            Regs[18] = (signed short)Objects[i]->y;
            Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[2]);                        //Init
            return(i);
        }
    }
    return(0xFFFF);
}

void ControlObjects(void)
{
    unsigned short i, o;
    unsigned short Class;
    signed short fx, fy, nx, ny, dx, dy, x, y;
    unsigned char PixelInfo, Collided;
    unsigned short ObjNum, SpriteLink, Template, Offset;
    unsigned char *FrameBuffer;

    for(i = 0; i < MAX_OBJECTS; i++)
    {
        if(Objects[i]->Used == 1)
        {
            Class = Objects[i]->Class;
            fx = (signed short)Objects[i]->x;
            fy = (signed short)Objects[i]->y;
            Objects[i]->x += Objects[i]->xv;
            Objects[i]->y += Objects[i]->yv;
            nx = (signed short)Objects[i]->x;
            ny = (signed short)Objects[i]->y;
            dx = nx - fx;
            dy = ny - fy;
            if(dx < 0)
                dx = -dx;
            if(dy < 0)
                dy = -dy;
            if((dx > 1) || (dy > 1))
            {
                Collided = CollisionTest((signed short *)&fx, (signed short *)&fy, (signed short *)&nx, (signed short *)&ny, MAP_SHOOTABLE, Classes[Class]->RunHitTests, (unsigned short *)&ObjNum);
            } else {
                Collided = (GetMapPixel((unsigned short)nx, (unsigned short)ny, 1) & MAP_SHOOTABLE) == 0;
                if(Classes[Class]->RunHitTests == 1)
                {
                    x = nx;
                    y = nx;
                    for(o = 0; o < MAX_HITTESTS; o++)
                    {
                        if(HitTests[o] == 0xFFFF)
                            break;
                        SpriteLink = Objects[HitTests[o]]->SpriteLink;
                        if(SpriteLink != 0xFFFF)
                        {
                            Template = Sprites[SpriteLink]->Template;
                            if((x >= Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame]) && (y >= Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) && (x < Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame] + Caches[Template]->w) && (y < Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame] + Caches[Template]->h))
                            {
                                Offset = x - Sprites[SpriteLink]->x + Caches[Template]->cx[Sprites[SpriteLink]->CurFrame];
                                Offset += (y - Sprites[SpriteLink]->y + Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) * Caches[Template]->w;
                                FrameBuffer = Caches[Template]->Frames[Sprites[SpriteLink]->CurFrame];
                                if(FrameBuffer[Offset] != 0)
                                {
                                    ObjNum = HitTests[o];
                                    Collided = 2;
                                }
                            }
                        }
                    }
                }
            }
            Objects[i]->yv += Gravity * ((float)Classes[Class]->GravityMod / 10000);
            if(Collided != 0)
            {
                PixelInfo = GetMapPixel((unsigned short)nx, (unsigned short)ny, 1);
                Regs[16] = i;
                Regs[17] = fx;
                Regs[18] = fy;
                Regs[19] = ((PixelInfo & MAP_SHOOTABLE) == 0)?0:1;
                Regs[20] = ((PixelInfo & MAP_WALKABLE) == 0)?0:1;
                Regs[21] = ((PixelInfo & MAP_DESTROYABLE) == 0)?0:1;
                Regs[22] = nx;
                Regs[23] = ny;
                Regs[24] = Collided;
                Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[1]);                        //Touch
            }
            if(Classes[Class]->TickDelay != 0)
            {
                if(++Objects[i]->TickTimer >= Classes[Class]->TickDelay)
                {
                    PixelInfo = GetMapPixel((unsigned short)Objects[i]->x, (unsigned short)Objects[i]->y, 1);
                    Objects[i]->TickTimer = 0;
                    Regs[16] = i;
                    Regs[17] = (signed short)Objects[i]->x;
                    Regs[18] = (signed short)Objects[i]->y;
                    Regs[19] = ((PixelInfo & MAP_SHOOTABLE) == 0)?0:1;
                    Regs[20] = ((PixelInfo & MAP_WALKABLE) == 0)?0:1;
                    Regs[21] = ((PixelInfo & MAP_DESTROYABLE) == 0)?0:1;
                    Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[0]);                    //Tick
                }
            }
            if(Objects[i]->SpriteLink != 0xFFFF)
            {
                Sprites[Objects[i]->SpriteLink]->x = (signed short)Objects[i]->x;
                Sprites[Objects[i]->SpriteLink]->y = (signed short)Objects[i]->y;
            }
        }
    }
}

void ControlSprites(void)
{
    unsigned short i;
    unsigned char Template;

    for(i = 0; i < MAX_SPRITES; i++)
    {
        if(Sprites[i]->Used == 1)
        {
            Template = Sprites[i]->Template;
            Sprites[i]->x += Sprites[i]->xv;
            Sprites[i]->y += Sprites[i]->yv;
            if(Caches[Template]->AnimDelay != 0xFF)
            {
                if(++Sprites[i]->AnimTimer >= Caches[Template]->AnimDelay)
                {
                    Sprites[i]->AnimTimer = 0;
                    if(++Sprites[i]->CurFrame >= Caches[Template]->NumFrames)
                    {
                        Sprites[i]->CurFrame = 0;
                        if(Sprites[i]->AnimCount > 0)
                        {
                            if(--Sprites[i]->AnimCount == 0)
                            {
                                Sprites[i]->Used = 0;
                            }
                        }
                    }
                }
            }
        }
    }
}

void ControlPixels(void)
{
    unsigned short i, o;
    signed short fx, fy, nx, ny, dx, dy, x, y;
    unsigned char Collided;
    unsigned short ObjNum, SpriteLink, Template, Offset;
    unsigned char *FrameBuffer;

    for(i = 0; i < MAX_PIXELS; i++)
    {
        if(Pixels[i]->Used == 1)
        {
            fx = (signed short)Pixels[i]->x;
            fy = (signed short)Pixels[i]->y;
            Pixels[i]->x += Pixels[i]->xv;
            Pixels[i]->y += Pixels[i]->yv;
            nx = (signed short)Pixels[i]->x;
            ny = (signed short)Pixels[i]->y;
            dx = nx - fx;
            dy = ny - fy;
            if(dx < 0)
                dx = -dx;
            if(dy < 0)
                dy = -dy;
            if((dx > 1) || (dy > 1))
            {
                Collided = CollisionTest((signed short *)&fx, (signed short *)&fy, (signed short *)&nx, (signed short *)&ny, MAP_SHOOTABLE, Pixels[i]->Explode, (unsigned short *)&ObjNum);
            } else {
                Collided = (GetMapPixel((unsigned short)Pixels[i]->x, (unsigned short)Pixels[i]->y, 1) & MAP_SHOOTABLE) == 0;
                if(Pixels[i]->Explode == 1)
                {
                    x = (signed short)Pixels[i]->x;
                    y = (signed short)Pixels[i]->y;
                    for(o = 0; o < MAX_HITTESTS; o++)
                    {
                        if(HitTests[o] == 0xFFFF)
                            break;
                        SpriteLink = Objects[HitTests[o]]->SpriteLink;
                        if(SpriteLink != 0xFFFF)
                        {
                            Template = Sprites[SpriteLink]->Template;
                            if((x >= Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame]) && (y >= Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) && (x < Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame] + Caches[Template]->w) && (y < Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame] + Caches[Template]->h))
                            {
                                Offset = x - Sprites[SpriteLink]->x + Caches[Template]->cx[Sprites[SpriteLink]->CurFrame];
                                Offset += (y - Sprites[SpriteLink]->y + Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) * Caches[Template]->w;
                                FrameBuffer = Caches[Template]->Frames[Sprites[SpriteLink]->CurFrame];
                                if(FrameBuffer[Offset] != 0)
                                {
                                    ObjNum = HitTests[o];
                                    Collided = 2;
                                }
                            }
                        }
                    }
                }
            }
            Pixels[i]->yv += Gravity;
            if(Collided != 0)
            {
                if(Pixels[i]->SetColor == 1)
                {
                    SetMapPixel((unsigned short)nx, (unsigned short)ny, Pixels[i]->c, 0);
                }
                if(Pixels[i]->SetColor == 2)
                {
                    SetMapPixel((unsigned short)fx, (unsigned short)fy, Pixels[i]->c, 0);
                    SetMapPixel((unsigned short)fx, (unsigned short)fy, MAP_DESTROYABLE, 1);
                }
                if(Pixels[i]->Explode == 1)
                {
                    if(Collided == 1)
                        SpawnExplosion((signed short)nx, (signed short)ny, 6, 0);
                    if(Collided == 2)
                    {
                        Regs[16] = (signed short)ObjNum;
                        Regs[17] = Pixels[i]->Damage;
                        Execute(Classes[Objects[ObjNum]->Class]->Code, (signed short *)&Objects[ObjNum]->Variables[0], Classes[Objects[ObjNum]->Class]->Scripts[3]);                        //TakeDamage
                    }
                }
                Pixels[i]->Used = 0;
            }
        }
    }
}

void CollVel(signed short x, signed short y, float *xv, float *yv, unsigned char Attributes)
{
    float Temp;
    signed char xa, ya;
    unsigned char a1, a2;

    if(*xv == 0)
    {
        *yv = -*yv;
        return;
    }
    if(*yv == 0)
    {
        *xv = -*xv;
        return;
    }
    if(*xv < 0)
        xa = -1;
    else
        xa = 1;
    if(*yv < 0)
        ya = -1;
    else
        ya = 1;
    a1 = GetMapPixel(x, y + ya, 1) & Attributes;
    a2 = GetMapPixel(x + xa, y, 1) & Attributes;
    if(((a1 == 0) && (a2 == 0)) || ((a1 != 0) && (a2 != 0)))
    {
        Temp = *yv;
        *yv = *xv * xa * ya;
        *xv = Temp * ya * xa;
    }
    if(a1 == 0)
        *yv = -*yv;
    if(a2 == 0)
        *xv = -*xv;
}

void ControlPlayers(void)
{
    unsigned short i, o;
    unsigned short ObjNum;
    signed short PlayerAngle, CurWeapon;

    for(i = 0; i < MAX_PLAYERS; i++)
    {
        if(Players[i]->Used == 1)
        {
            for(o = 0; o < NUM_WEAPONS; o++)
            {
                if(PWeapons[i][o]->FireTimer > 0)
                {
                    if(++PWeapons[i][o]->FireTimer > Weapons[PWeapons[i][o]->Weapon]->FireDelay)
                        PWeapons[i][o]->FireTimer = 0;
                }
                if((PWeapons[i][o]->ReloadTimer > 0) && (Players[i]->CurWeapon == o))
                {
                    if(++PWeapons[i][o]->ReloadTimer > Weapons[PWeapons[i][o]->Weapon]->ReloadDelay)
                    {
                        PWeapons[i][o]->ReloadTimer = 0;
                        PWeapons[i][o]->AmmoLeft = Weapons[PWeapons[i][o]->Weapon]->Ammo;
                    }
                }
            }
            ObjNum = Players[i]->Object;
            Players[i]->Angle += Players[i]->AngleVel;
            if(Players[i]->Angle >= 360)
                Players[i]->Angle -= 360;
            if(Players[i]->Angle < 0)
                Players[i]->Angle += 360;
            if((Players[i]->Angle < 300) && (Players[i]->Angle > 180))
            {
                Players[i]->Angle = 300;
                Players[i]->AngleVel = 0;
            }
            if((Players[i]->Angle > 90) && (Players[i]->Angle <= 180))
            {
                Players[i]->Angle = 90;
                Players[i]->AngleVel = 0;
            }
            if(((Players[i]->Left != 0) ^ (Players[i]->Right != 0)) & (Players[i]->Change == 0))
            {
                if((Players[i]->Left != 0) && (Objects[ObjNum]->xv > -1))
                {
                    if((GetMapPixel((unsigned short)(Objects[ObjNum]->x) - 1, (unsigned short)(Objects[ObjNum]->y) - 1, 1) & MAP_WALKABLE) == MAP_WALKABLE)
                        Objects[ObjNum]->xv -= 0.1;
                    Players[i]->Dir = 1;
                }
                if((Players[i]->Right != 0) && (Objects[ObjNum]->xv < 1))
                {
                    if((GetMapPixel((unsigned short)(Objects[ObjNum]->x) + 1, (unsigned short)(Objects[ObjNum]->y) - 1, 1) & MAP_WALKABLE) == MAP_WALKABLE)
                        Objects[ObjNum]->xv += 0.1;
                    Players[i]->Dir = 0;
                }
            } else {
                if((GetMapPixel((unsigned short)Objects[ObjNum]->x, (unsigned short)Objects[ObjNum]->y, 1) & MAP_WALKABLE) == 0)
                    Objects[ObjNum]->xv *= 0.9;
            }
            if((Players[i]->Change != 0) && (Players[i]->Left == 1))
            {
                Players[i]->CurWeapon -= 1;
                if(Players[i]->CurWeapon < 0)
                    Players[i]->CurWeapon += NUM_WEAPONS;
                while(PWeapons[i][Players[i]->CurWeapon]->Used == 0)
                {
                    Players[i]->CurWeapon -= 1;
                    if(Players[i]->CurWeapon < 0)
                        Players[i]->CurWeapon += NUM_WEAPONS;
                }
            }
            if((Players[i]->Change != 0) && (Players[i]->Right == 1))
            {
                Players[i]->CurWeapon += 1;
                if(Players[i]->CurWeapon >= NUM_WEAPONS)
                    Players[i]->CurWeapon -= NUM_WEAPONS;
                while(PWeapons[i][Players[i]->CurWeapon]->Used == 0)
                {
                    Players[i]->CurWeapon += 1;
                    if(Players[i]->CurWeapon >= NUM_WEAPONS)
                        Players[i]->CurWeapon -= NUM_WEAPONS;
                }
            }
            if((Players[i]->Up != 0) ^ (Players[i]->Down != 0))
            {
                if((Players[i]->Up != 0) && (Players[i]->AngleVel < 3))
                    Players[i]->AngleVel += .5;
                if((Players[i]->Down != 0) && (Players[i]->AngleVel > -3))
                    Players[i]->AngleVel -= .5;
            } else {
                Players[i]->AngleVel *= .75;
            }
            PlayerAngle = Players[i]->Angle;
            if(PlayerAngle > 90)
                PlayerAngle -= 360;
            if(Players[i]->Dir == 1)
                PlayerAngle = 180 - PlayerAngle;
            if(PlayerAngle < 0)
                PlayerAngle += 360;
            CurWeapon = Players[i]->CurWeapon;
            if((Players[i]->Shoot != 0) && (PWeapons[i][CurWeapon]->FireTimer == 0) && (PWeapons[i][CurWeapon]->ReloadTimer == 0))
            {
                PWeapons[i][Players[i]->CurWeapon]->FireTimer = 1;
                if(Players[i]->Dir == 0)
                {
                    Regs[16] = (signed short)Objects[ObjNum]->x + 3 + Cosine[PlayerAngle] * 7;
                } else {
                    Regs[16] = (signed short)Objects[ObjNum]->x - 1 + Cosine[PlayerAngle] * 7;
                }
                Regs[17] = (signed short)Objects[ObjNum]->y - 2 - Sine[PlayerAngle] * 7;
                Regs[18] = (signed short)PlayerAngle;
                Regs[19] = (signed short)(Objects[ObjNum]->xv * 100);
                Regs[20] = (signed short)(Objects[ObjNum]->yv * 100);
                Regs[21] = (signed short)i;
                Execute(Classes[Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->Class]->Code, (signed short *)&PWeapons[i][Players[i]->CurWeapon]->Vars[0], Classes[Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->Class]->Scripts[0]);              //Fire
                LastShot = Regs[16];
                if(--PWeapons[i][CurWeapon]->AmmoLeft <= 0)
                    PWeapons[i][CurWeapon]->ReloadTimer = 1;
            }
        }
    }
}

void SpawnExplosion(signed short x, signed short y, unsigned char StartFrame, unsigned char Smokes)
{
    unsigned short i, Result;

    Result = SpawnSprite(0, x, y, 0, 0, 1, StartFrame);
    CopyToMap(x - Caches[0]->cx[StartFrame], y - Caches[0]->cy[StartFrame], Caches[0]->Frames[StartFrame], Caches[0]->w, Caches[0]->h, 0, 1, 0, MAP_WALKABLE | MAP_SHOOTABLE | MAP_DESTROYABLE);
    if(Smokes > 0)
    {
        for(i = 0; i < Smokes; i++)
        {
            SpawnSprite(1, x + ((signed short)(rand() % 10) - 5), y + ((signed short)(rand() % 10) - 5), 0, -1, 1, 0);
        }
    }
}

unsigned char ArgExist(int argc, char *argv[], char *Match)
{
    int i;

    for(i = 0; i < argc; i++)
    {
        if(strcmp(strupr((char *)argv[i]), strupr((char *)Match)) == 0)
            return(1);
    }
    return(0);
}

int main(int argc, char *argv[])
{
    unsigned short Result, x, y, i;
    unsigned short Attributes, Size;
    unsigned long Cycles;
    unsigned char Finished;
    unsigned short CoreObject;
    unsigned char c0, c1, c2, c3, c4;
    unsigned char MFR;
    unsigned long Start;

    DebugMode = 0;
    MFR = 0;
    if(argc > 1)
    {
        if(ArgExist(argc, argv, "/Debug") == 1)
            DebugMode = 1;
        if(ArgExist(argc, argv, "/FR") == 1)
            MFR = 1;
    }
    switch(Init(&Result))
    {
        case 0:
            if(Result == 0x40) printf("EMS not installed!\nQuitting...\n"); else printf("EMS failure!\nError code: %u\nQuitting...\n", (unsigned short)Result);
            getch();
            Terminate();
            return;
        case 1:
            printf("Internal EMS failure!\nQuitting...\n");
            getch();
            Terminate();
            return;
        case 2:
            printf("Not enough memory!\n");
            getch();
            Terminate();
            return;
        case 3:
            printf("Couldn't find the file KVID.DAT!\n");
            getch();
            Terminate();
            return;
        case 4:
            printf("Datafile corrupted!\n");
            getch();
            Terminate();
            return;
        case 5:
            printf("Not enough EMS memory available\nAt least %lu KB needed!\n", MaxLW * MaxLH * 64 * NUM_PLANES);
            getch();
            Terminate();
            return;
    }
    for(y = 0; y < LevelHeight; y++)
    {
        for(x = 0; x < LevelWidth; x++)
        {
            SetMapPixel(x, y, (x + y) & 0xFF, 0);
        }
        ShowMap(0, 0, 319, 199, 0, 0);
        DisplayDB();
    }
    Terminate();
    return(0);
    Players[0]->Used = 1;
    Players[1]->Used = 1;
    for(y=0;y<LevelHeight;y++)
    {
        for(x=0;x<LevelWidth;x++)
        {
            SetMapPixel(x, y, (unsigned char)((rand() % 4) + 44), 0);
        }
    }
    for(y = 0; y < LevelHeight; y++)
    {
        for(x = 0; x < LevelWidth; x++)
        {
            c0 = GetMapPixel(x, y, 0);
            c1 = GetMapPixel(x - 1, y, 0);
            c2 = GetMapPixel(x + 1, y, 0);
            c3 = GetMapPixel(x, y - 1, 0);
            c4 = GetMapPixel(x, y + 1, 0);
            c1 = (c1 == 0)?c0:c1;
            c2 = (c2 == 0)?c0:c2;
            c3 = (c3 == 0)?c0:c3;
            c4 = (c4 == 0)?c0:c4;
            SetMapPixel(x, y, (unsigned char)((c1 + c2 + c3 + c4) >> 2), 0);
        }
    }
    for(y=0;y<LevelHeight;y++)
    {
        for(x=0;x<LevelWidth;x++)
        {
            SetMapPixel(x, y, MAP_DESTROYABLE, 1);
        }
    }
    for(x = 320; x < LevelWidth; x += 320)
    {
        for(y = 0; y < LevelHeight; y++)
        {
            SetMapPixel(x, y, 40, 0);
            SetMapPixel(x, y, MAP_WALKABLE | MAP_SHOOTABLE, 1);
        }
    }
    for(y = 200; y < LevelHeight; y += 200)
    {
        for(x = 0; x < LevelWidth; x++)
        {
            SetMapPixel(x, y, 40, 0);
            SetMapPixel(x, y, MAP_WALKABLE | MAP_SHOOTABLE, 1);
        }
    }
    for(i = 0; i < 200; i++)
    {
        x = rand() % LevelWidth;
        y = rand() % LevelHeight;
        CopyToMap(x - 15, y - 11, Caches[11]->Frames[rand() % 8], Caches[11]->w, Caches[11]->h, 0, 0, 0, 0);
    }
    for(i = 0; i < 300; i++)
    {
        x = rand() % LevelWidth;
        y = rand() % LevelHeight;
        CopyToMap(x - Caches[0]->cx[0], y - Caches[0]->cy[0], Caches[0]->Frames[0], Caches[0]->w, Caches[0]->h, 0, 1, 0, MAP_SHOOTABLE | MAP_WALKABLE | MAP_DESTROYABLE);
    }
    CoreObject = SpawnObject(0, 0, 0, 0, 0, 0);
    Cycles = 0;
    Finished = 0;
    InitVar();
    if(MFR == 1)
    {
        Start = (unsigned long)time(NULL);
        while((unsigned long)time(NULL) == Start);
        Start = (unsigned long)time(NULL);
    }
    while(Finished == 0)
    {
        if((ReadyToGo == 1) || (MFR == 1))
        {
            if(KeyTable[67])
                DebugMode = 1;
            if(KeyTable[68])
                DebugMode = 0;
            for(i = 0; i < MAX_PLAYERS; i++)
            {
                Players[i]->Left = 0;
                Players[i]->Right = 0;
                Players[i]->Up = 0;
                Players[i]->Down = 0;
                Players[i]->Shoot = 0;
                Players[i]->Change = 0;
            }
            GetInputs();
            ControlPixels();
            ControlSprites();
            ControlObjects();
            ControlPlayers();
            Cycles++;
            if(KeyTable[1] == 1) Finished = 1;
            if(MFR == 1)
                if((unsigned long)time(NULL) - Start > 10)
                    Finished = 1;
            c0 = KeyTable[63] * 4;
            if(KeyTable[64] == 1) c0 += 8;
            if(KeyTable[59] == 1) BGFrame = c0;
            if(KeyTable[60] == 1) BGFrame = c0 + 1;
            if(KeyTable[61] == 1) BGFrame = c0 + 2;
            if(KeyTable[62] == 1) BGFrame = c0 + 3;
            DrawScreen();
            for(i = 0; i < MAX_LINES; i++)
            {
                Lines[i]->Used = 0;
            }
            DBPSet(0, 199, Cycles & 0xFF);
            DisplayDB();
            ReadyToGo = 0;
        }
    }
    Terminate();
    printf("%lu", Cycles);
    return(0);
}


More information about the Gcc-prs mailing list