Initial commit
authorFredrik Tolf <fredrik@dolda2000.com>
Fri, 23 Nov 2007 14:37:11 +0000 (15:37 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Fri, 23 Nov 2007 14:37:39 +0000 (15:37 +0100)
14 files changed:
Makefile [new file with mode: 0644]
dblbuf.c [new file with mode: 0644]
dblbuf.h [new file with mode: 0644]
executor.c [new file with mode: 0644]
executor.h [new file with mode: 0644]
fileio.c [new file with mode: 0644]
fileio.h [new file with mode: 0644]
kvidha.c [new file with mode: 0644]
kvidha.h [new file with mode: 0644]
newdb.asm [new file with mode: 0644]
newdb.h [new file with mode: 0644]
sb.c [new file with mode: 0644]
sb.h [new file with mode: 0644]
sdlmap.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..62bf8b4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+default: kvidha
+
+LDFLAGS := -g
+CFLAGS := -g
+
+kvidha: kvidha.o dblbuf.o executor.o fileio.o sb.o
+       gcc $(LDFLAGS) -o $@ $^ -lSDL
+
+%.o: %.c
+       gcc $(CFLAGS) -c -o $@ $<
diff --git a/dblbuf.c b/dblbuf.c
new file mode 100644 (file)
index 0000000..3dae392
--- /dev/null
+++ b/dblbuf.c
@@ -0,0 +1,1151 @@
+#include "executor.h"\r
+#include "kvidha.h"\r
+#include "sb.h"\r
+#include "newdb.h"\r
+\r
+static unsigned char MMXBuffer[8];\r
+\r
+void DBFillScreen(unsigned long c)\r
+{\r
+    int i;\r
+    unsigned long *p;\r
+    \r
+    p = (unsigned long *)DblBuffer;\r
+    for(i = 0; i < 64000; i++)\r
+       *(p++) = c;\r
+}\r
+\r
+void DBSetClip(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2)\r
+{\r
+    clip_x1 = x1;\r
+    clip_x2 = x2;\r
+    clip_y1 = y1;\r
+    clip_y2 = y2;\r
+}\r
+\r
+unsigned long DBPoint(unsigned short x, unsigned short y)\r
+{\r
+    return(*(unsigned long *)&DblBuffer[((unsigned long)y << 10) + ((unsigned long)y << 8) + ((unsigned long)x << 2)]);\r
+}\r
+\r
+/*void DBPSet(unsigned short x, unsigned short y, unsigned long c)\r
+{\r
+    *(unsigned long *)&DblBuffer[((unsigned long)y << 10) + ((unsigned long)y << 8) + ((unsigned long)x << 2)] = c;\r
+}*/\r
+\r
+void DBPSetC(unsigned short x, unsigned short y, unsigned long c)\r
+{\r
+    if ((x >= clip_x1) && (x <= clip_x2) && (y >= clip_y1) && (y <= clip_y2))\r
+        *(unsigned long *)&DblBuffer[((unsigned long)y << 10) + ((unsigned long)y << 8) + ((unsigned long)x << 2)] = c;\r
+}\r
+\r
+void DBPSetCTrans(unsigned short x, unsigned short y, unsigned long c, unsigned char Method)\r
+{\r
+    if ((x >= clip_x1) && (x <= clip_x2) && (y >= clip_y1) && (y <= clip_y2))\r
+        TransOps[Method]((unsigned long *)&DblBuffer[((unsigned long)y << 10) + ((unsigned long)y << 8) + ((unsigned long)x << 2)], c);\r
+}\r
+\r
+void DBFRect(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned long c)\r
+{\r
+    unsigned short y, x;\r
+\r
+    for(y = y1; y <= y2; y++)\r
+    {\r
+        for(x = x1; x <= x2; x++)\r
+        {\r
+            DBPSetC(x, y, c);\r
+        }\r
+    }\r
+}\r
+\r
+void DBFRectTrans(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned long c, unsigned char Method)\r
+{\r
+    unsigned short y, x;\r
+\r
+    for(y = y1; y <= y2; y++)\r
+    {\r
+        for(x = x1; x <= x2; x++)\r
+        {\r
+            DBPSetCTrans(x, y, c, Method);\r
+        }\r
+    }\r
+}\r
+\r
+void DBFCircle(signed short x, signed short y, unsigned short r, unsigned long Color, unsigned char Filled, float Aspect)\r
+{\r
+    signed short y1, y2, x1, x2;\r
+    signed short cy, cx;\r
+    unsigned long r2;\r
+\r
+    if(y - r < clip_y1)\r
+    {\r
+        y1 = clip_y1;\r
+        cy = clip_y1 - y;\r
+    } else {\r
+        y1 = y - r;\r
+        cy = -r;\r
+    }\r
+    if(y + r > clip_y2)\r
+        y2 = clip_y2 - y;\r
+    else\r
+        y2 = r;\r
+    for(r2 = (unsigned long)r * (unsigned long)r; cy <= y2; cy++)\r
+    {\r
+        x1 = x - (x2 = (sqrt(r2 - ((unsigned long)cy * (unsigned long)cy)) * Aspect));\r
+        x2 += x;\r
+        if(Filled == 1)\r
+        {\r
+            if(x1 < clip_x1)\r
+                x1 = clip_x1;\r
+            if(x2 > clip_x2)\r
+                x2 = clip_x2;\r
+            for(cx = x1; cx <= x2; cx++)\r
+                DBPSetC(cx, y1, Color);\r
+        } else {\r
+            DBPSetC(x1, y1, Color);\r
+            DBPSetC(x2, y1, Color);\r
+        }\r
+        y1++;\r
+    }\r
+}\r
+\r
+void DBFCircleTrans(signed short x, signed short y, unsigned short r, unsigned long Color, unsigned char Filled, float Aspect, unsigned char Method)\r
+{\r
+    signed short y1, y2, x1, x2;\r
+    signed short cy, cx;\r
+    unsigned long r2;\r
+\r
+    if(y - r < clip_y1)\r
+    {\r
+        y1 = clip_y1;\r
+        cy = clip_y1 - y;\r
+    } else {\r
+        y1 = y - r;\r
+        cy = -r;\r
+    }\r
+    if(y + r > clip_y2)\r
+        y2 = clip_y2 - y;\r
+    else\r
+        y2 = r;\r
+    for(r2 = (unsigned long)r * (unsigned long)r; cy <= y2; cy++)\r
+    {\r
+        x1 = x - (x2 = (sqrt(r2 - ((unsigned long)cy * (unsigned long)cy)) * Aspect));\r
+        x2 += x;\r
+        if(Filled == 1)\r
+        {\r
+            if(x1 < clip_x1)\r
+                x1 = clip_x1;\r
+            if(x2 > clip_x2)\r
+                x2 = clip_x2;\r
+            for(cx = x1; cx <= x2; cx++)\r
+                DBPSetCTrans(cx, y1, Color, Method);\r
+        } else {\r
+            DBPSetCTrans(x1, y1, Color, Method);\r
+            DBPSetCTrans(x2, y1, Color, Method);\r
+        }\r
+        y1++;\r
+    }\r
+}\r
+\r
+void DBFCircleFadedTrans(signed short x, signed short y, unsigned short r, unsigned long Color, float Aspect, unsigned char Method)\r
+{\r
+    signed short y1, y2, x1, x2;\r
+    signed short cy, cx;\r
+    unsigned long r2;\r
+    struct ColorType MainColor, MidColor, CurColor;\r
+    unsigned short RE, GE, BE;\r
+    signed char Inc;\r
+\r
+    if(y - r < clip_y1)\r
+    {\r
+        y1 = clip_y1;\r
+        cy = clip_y1 - y;\r
+    } else {\r
+        y1 = y - r;\r
+        cy = -r;\r
+    }\r
+    if(y + r > clip_y2)\r
+        y2 = clip_y2 - y;\r
+    else\r
+        y2 = r;\r
+    MainColor = *(struct ColorType *)&Color;\r
+    for(r2 = (unsigned long)r * (unsigned long)r; cy <= y2; cy++)\r
+    {\r
+        if(cy < 0)\r
+        {\r
+            MidColor.R = (unsigned char)(((unsigned long)MainColor.R * (unsigned long)(r + cy)) / (unsigned long)r);\r
+            MidColor.G = (unsigned char)(((unsigned long)MainColor.G * (unsigned long)(r + cy)) / (unsigned long)r);\r
+            MidColor.B = (unsigned char)(((unsigned long)MainColor.B * (unsigned long)(r + cy)) / (unsigned long)r);\r
+        } else {\r
+            MidColor.R = (unsigned char)(((unsigned long)MainColor.R * (unsigned long)(r - cy)) / (unsigned long)r);\r
+            MidColor.G = (unsigned char)(((unsigned long)MainColor.G * (unsigned long)(r - cy)) / (unsigned long)r);\r
+            MidColor.B = (unsigned char)(((unsigned long)MainColor.B * (unsigned long)(r - cy)) / (unsigned long)r);\r
+        }\r
+        *(unsigned long *)&CurColor = 0;\r
+        RE = GE = BE = 0;\r
+        x1 = x - (x2 = (sqrt(r2 - ((unsigned long)cy * (unsigned long)cy)) * Aspect));\r
+        x2 += x;\r
+        Inc = 1;\r
+        if(x1 < clip_x1)\r
+        {\r
+            CurColor.R = (unsigned char)(((unsigned long)(clip_x1 - x1) * (unsigned long)MidColor.R) / (unsigned long)r);\r
+            CurColor.G = (unsigned char)(((unsigned long)(clip_x1 - x1) * (unsigned long)MidColor.G) / (unsigned long)r);\r
+            CurColor.B = (unsigned char)(((unsigned long)(clip_x1 - x1) * (unsigned long)MidColor.B) / (unsigned long)r);\r
+            x1 = clip_x1;\r
+            if(x1 > x)\r
+                Inc = -1;\r
+        }\r
+        if(x2 > clip_x2)\r
+            x2 = clip_x2;\r
+        for(cx = x1; cx <= x2; cx++)\r
+        {\r
+            if(cx == x)\r
+            {\r
+                Inc = -1;\r
+                RE = GE = BE = 0;\r
+            }\r
+            DBPSetCTrans(cx, y1, *(unsigned long *)&CurColor, Method);\r
+            RE += (unsigned short)MidColor.R;\r
+            GE += (unsigned short)MidColor.G;\r
+            BE += (unsigned short)MidColor.B;\r
+            while(RE > r)\r
+            {\r
+                RE -= r;\r
+                CurColor.R += Inc;\r
+            }\r
+            while(GE > r)\r
+            {\r
+                GE -= r;\r
+                CurColor.G += Inc;\r
+            }\r
+            while(BE > r)\r
+            {\r
+                BE -= r;\r
+                CurColor.B += Inc;\r
+            }\r
+        }\r
+        y1++;\r
+    }\r
+}\r
+\r
+void DBFPoly(signed short x1, signed short y1, signed short x2, signed short y2, signed short x3, signed short y3, unsigned long Color)\r
+{\r
+    signed short x[3], y[3], Temp, m1, m2;\r
+    signed short i, o, StartX, StopX;\r
+    signed long k1, k2, cx1, cx2;\r
+\r
+    x[0] = x1; y[0] = y1;\r
+    x[1] = x2; y[1] = y2;\r
+    x[2] = x3; y[2] = y3;\r
+    for(i = 0; i < 2; i++)\r
+    {\r
+        for(o = i + 1; o < 3; o++)\r
+        {\r
+            if(y[o] < y[i])\r
+            {\r
+                Temp = y[o];\r
+                y[o] = y[i];\r
+                y[i] = Temp;\r
+                Temp = x[o];\r
+                x[o] = x[i];\r
+                x[i] = Temp;\r
+            }\r
+        }\r
+    }\r
+    cx1 = cx2 = x[0] << 16;\r
+    if(y[0] == y[1])\r
+    {\r
+        cx1 = x[1] << 16;\r
+    } else {\r
+        k1 = ((signed long)(x[1] - x[0]) << 16) / (signed long)(y[1] - y[0]);\r
+        k2 = ((signed long)(x[2] - x[0]) << 16) / (signed long)(y[2] - y[0]);\r
+        for(i = y[0]; i <= y[1]; i++)\r
+        {\r
+            if((i >= clip_y1) && (i <= clip_y2))\r
+            {\r
+                if(cx1 > cx2)\r
+                {\r
+                    StartX = cx2 >> 16;\r
+                    StopX = cx1 >> 16;\r
+                } else {\r
+                    StartX = cx1 >> 16;\r
+                    StopX = cx2 >> 16;\r
+                }\r
+                if(StartX < clip_x1)\r
+                    StartX = clip_x1;\r
+                if(StopX > clip_x2)\r
+                    StopX = clip_x2;\r
+                if((StartX <= clip_x2) && (StopX >= clip_x1))\r
+                {\r
+                    for(o = StartX; o <= StopX; o++)\r
+                        DBPSetC(o, i, Color);\r
+                }\r
+            }\r
+            /*asm("\r
+            cld\r
+            rep stosl\r
+            "\r
+            :\r
+            : "a" (Color), "c" ((abs(x1 - x2) >> 16) + 1), "D" ((unsigned long)DblBuffer + ((unsigned long)i << 10) + ((unsigned long)i << 8) + (((x1 < x2)?x1:x2) >> 14))\r
+            );*/\r
+            cx1 += k1;\r
+            cx2 += k2;\r
+        }\r
+    }\r
+    if(y[1] == y[2])\r
+        return;\r
+    k1 = ((signed long)(x[2] - x[1]) << 16) / (signed long)(y[2] - y[1]);\r
+    k2 = ((signed long)(x[2] - x[0]) << 16) / (signed long)(y[2] - y[0]);\r
+    for(i = y[1] + 1; i <= y[2]; i++)\r
+    {\r
+        if((i >= clip_y1) && (i <= clip_y2))\r
+        {\r
+            if(cx1 > cx2)\r
+            {\r
+                StartX = cx2 >> 16;\r
+                StopX = cx1 >> 16;\r
+            } else {\r
+                StartX = cx1 >> 16;\r
+                StopX = cx2 >> 16;\r
+            }\r
+            if(StartX < clip_x1)\r
+                StartX = clip_x1;\r
+            if(StopX > clip_x2)\r
+                StopX = clip_x2;\r
+            if((StartX <= clip_x2) && (StopX >= clip_x1))\r
+            {\r
+                for(o = StartX; o <= StopX; o++)\r
+                    DBPSetC(o, i, Color);\r
+            }\r
+        }\r
+        /*asm("\r
+        cld\r
+        rep stosl\r
+        "\r
+        :\r
+        : "a" (Color), "c" ((abs(x1 - x2) >> 16) + 1), "D" ((unsigned long)DblBuffer + ((unsigned long)i << 10) + ((unsigned long)i << 8) + (((x1 < x2)?x1:x2) >> 14))\r
+        );*/\r
+        cx1 += k1;\r
+        cx2 += k2;\r
+    }\r
+}\r
+\r
+void DBFPolyTrans(signed short x1, signed short y1, signed short x2, signed short y2, signed short x3, signed short y3, unsigned long Color, unsigned char Method)\r
+{\r
+    signed short x[3], y[3], Temp, m1, m2;\r
+    signed short i, o, StartX, StopX;\r
+    signed long k1, k2, cx1, cx2;\r
+\r
+    x[0] = x1; y[0] = y1;\r
+    x[1] = x2; y[1] = y2;\r
+    x[2] = x3; y[2] = y3;\r
+    for(i = 0; i < 2; i++)\r
+    {\r
+        for(o = i + 1; o < 3; o++)\r
+        {\r
+            if(y[o] < y[i])\r
+            {\r
+                Temp = y[o];\r
+                y[o] = y[i];\r
+                y[i] = Temp;\r
+                Temp = x[o];\r
+                x[o] = x[i];\r
+                x[i] = Temp;\r
+            }\r
+        }\r
+    }\r
+    cx1 = cx2 = x[0] << 16;\r
+    if(y[0] == y[1])\r
+    {\r
+        cx1 = x[1] << 16;\r
+    } else {\r
+        k1 = ((signed long)(x[1] - x[0]) << 16) / (signed long)(y[1] - y[0]);\r
+        k2 = ((signed long)(x[2] - x[0]) << 16) / (signed long)(y[2] - y[0]);\r
+        for(i = y[0]; i <= y[1]; i++)\r
+        {\r
+            if((i >= clip_y1) && (i <= clip_y2))\r
+            {\r
+                if(cx1 > cx2)\r
+                {\r
+                    StartX = cx2 >> 16;\r
+                    StopX = cx1 >> 16;\r
+                } else {\r
+                    StartX = cx1 >> 16;\r
+                    StopX = cx2 >> 16;\r
+                }\r
+                if(StartX < clip_x1)\r
+                    StartX = clip_x1;\r
+                if(StopX > clip_x2)\r
+                    StopX = clip_x2;\r
+                if((StartX <= clip_x2) && (StopX >= clip_x1))\r
+                {\r
+                    for(o = StartX; o <= StopX; o++)\r
+                        DBPSetCTrans(o, i, Color, Method);\r
+                }\r
+            }\r
+            cx1 += k1;\r
+            cx2 += k2;\r
+        }\r
+        cx1 -= k1;\r
+        cx2 -= k2;\r
+    }\r
+    if(y[1] == y[2])\r
+        return;\r
+    k1 = ((signed long)(x[2] - x[1]) << 16) / (signed long)(y[2] - y[1]);\r
+    k2 = ((signed long)(x[2] - x[0]) << 16) / (signed long)(y[2] - y[0]);\r
+    for(i = y[1] + 1; i <= y[2]; i++)\r
+    {\r
+        if((i >= clip_y1) && (i <= clip_y2))\r
+        {\r
+            if(cx1 > cx2)\r
+            {\r
+                StartX = cx2 >> 16;\r
+                StopX = cx1 >> 16;\r
+            } else {\r
+                StartX = cx1 >> 16;\r
+                StopX = cx2 >> 16;\r
+            }\r
+            if(StartX < clip_x1)\r
+                StartX = clip_x1;\r
+            if(StopX > clip_x2)\r
+                StopX = clip_x2;\r
+            if((StartX <= clip_x2) && (StopX >= clip_x1))\r
+            {\r
+                for(o = StartX; o <= StopX; o++)\r
+                    DBPSetCTrans(o, i, Color, Method);\r
+            }\r
+        }\r
+        cx1 += k1;\r
+        cx2 += k2;\r
+    }\r
+}\r
+\r
+void DBLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2)\r
+{\r
+    signed short dx, dy, x, y;\r
+    signed short xi, yi, d;\r
+    unsigned short i;\r
+    unsigned char c;\r
+\r
+    dx = x2 - x1;\r
+    dy = y2 - y1;\r
+    if(dx >= 0)\r
+    {\r
+        xi = 1;\r
+    } else {\r
+        xi = -1;\r
+        dx = -dx;\r
+    }\r
+    if(dy >= 0)\r
+    {\r
+        yi = 1;\r
+    } else {\r
+        yi = -1;\r
+        dy = -dy;\r
+    }\r
+    d = 0;\r
+    x = x1;\r
+    y = y1;\r
+    c = 0;\r
+    if(dx > dy)\r
+    {\r
+        for(i = 0; i <= dx; i++)\r
+        {\r
+            DBPSetC((unsigned short)x, (unsigned short)y, ((c ^= 1) == 0)?c2:c1);\r
+            d += dy;\r
+            if(d > dx)\r
+            {\r
+                d -= dx;\r
+                y += yi;\r
+            }\r
+            x += xi;\r
+        }\r
+    } else {\r
+        for(i = 0; i <= dy; i++)\r
+        {\r
+            DBPSetC((unsigned short)x, (unsigned short)y, ((c ^= 1) == 0)?c2:c1);\r
+            d += dx;\r
+            if(d > 0)\r
+            {\r
+                d -= dy;\r
+                x += xi;\r
+            }\r
+            y += yi;\r
+        }\r
+    }\r
+}\r
+\r
+void DBLineTrans(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2, unsigned char Method)\r
+{\r
+    signed short dx, dy, x, y;\r
+    signed short xi, yi, d;\r
+    unsigned short i;\r
+    unsigned char c;\r
+\r
+    dx = x2 - x1;\r
+    dy = y2 - y1;\r
+    if(dx >= 0)\r
+    {\r
+        xi = 1;\r
+    } else {\r
+        xi = -1;\r
+        dx = -dx;\r
+    }\r
+    if(dy >= 0)\r
+    {\r
+        yi = 1;\r
+    } else {\r
+        yi = -1;\r
+        dy = -dy;\r
+    }\r
+    d = 0;\r
+    x = x1;\r
+    y = y1;\r
+    c = 0;\r
+    if(dx > dy)\r
+    {\r
+        for(i = 0; i <= dx; i++)\r
+        {\r
+            DBPSetCTrans((unsigned short)x, (unsigned short)y, ((c ^= 1) == 0)?c2:c1, Method);\r
+            d += dy;\r
+            if(d > dx)\r
+            {\r
+                d -= dx;\r
+                y += yi;\r
+            }\r
+            x += xi;\r
+        }\r
+    } else {\r
+        for(i = 0; i <= dy; i++)\r
+        {\r
+            DBPSetCTrans((unsigned short)x, (unsigned short)y, ((c ^= 1) == 0)?c2:c1, Method);\r
+            d += dx;\r
+            if(d > 0)\r
+            {\r
+                d -= dy;\r
+                x += xi;\r
+            }\r
+            y += yi;\r
+        }\r
+    }\r
+}\r
+\r
+void DBCopyBuffer(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc)\r
+{\r
+    unsigned char *WorkOffset;\r
+    unsigned long offset;\r
+    unsigned long OffsetAdd;\r
+    unsigned short cx, cy;\r
+    unsigned long data;\r
+\r
+    offset = 0;\r
+    WorkOffset = DblBuffer + ((signed long)y << 10) + ((signed long)y << 8) + ((signed long)x << 2);\r
+    OffsetAdd = 1280 - (w << 2);\r
+    for(cy = 0; cy < h; cy++)\r
+    {\r
+        for(cx = 0; cx < w; cx++)\r
+        {\r
+            data = *(unsigned long *)Buffer;\r
+            if(data != bgc)\r
+                *(unsigned long *)WorkOffset = data;\r
+            Buffer += 4;\r
+            WorkOffset += 4;\r
+        }\r
+        WorkOffset += OffsetAdd;\r
+    }\r
+/*\r
+    DBCopyBufferAsm(x, y, Buffer, w, h, bgc);\r
+*/\r
+}\r
+\r
+void DBCopyBufferClip(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc)\r
+{\r
+    unsigned char *WorkOffset;\r
+    unsigned long OffsetAdd1, OffsetAdd2;\r
+    signed short cx, cy, sx, sy, cw, ch;\r
+    unsigned long data;\r
+\r
+    if((x > clip_x2) || ((x + w) < clip_x1) || (y > clip_y2) || ((y + h) < clip_y1))\r
+        return;\r
+    if((x >= clip_x1) && ((x + w) <= clip_x2) && (y >= clip_y1) && ((y + h) <= clip_y2))\r
+    {\r
+        DBCopyBuffer(x, y, Buffer, w, h, bgc);\r
+        return;\r
+    }\r
+    sx = (x < clip_x1)?(clip_x1 - x):0;\r
+    sy = (y < clip_y1)?(clip_y1 - y):0;\r
+    cw = (x + (signed short)w - 1 > clip_x2)?(clip_x2 - x + 1):(signed short)w;\r
+    ch = (y + (signed short)h - 1 > clip_y2)?(clip_y2 - y + 1):(signed short)h;\r
+    Buffer += (sx + (sy * w)) << 2;\r
+    OffsetAdd1 = (sx + w - cw) << 2;\r
+    OffsetAdd2 = 1280 - ((cw - sx) << 2);\r
+    WorkOffset = DblBuffer + ((signed long)(y + sy) << 10) + ((signed long)(y + sy) << 8) + ((signed long)(x + sx) << 2);\r
+    for(cy = 0; cy < ch - sy; cy++)\r
+    {\r
+        for(cx = 0; cx < cw - sx; cx++)\r
+        {\r
+            data = *(unsigned long *)Buffer;\r
+            if(data != bgc)\r
+                *(unsigned long *)WorkOffset = data;\r
+            Buffer += 4;\r
+            WorkOffset += 4;\r
+        }\r
+        Buffer += OffsetAdd1;\r
+        WorkOffset += OffsetAdd2;\r
+    }\r
+}\r
+\r
+void DBSpriteLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned char *Buffer, unsigned short w, unsigned short h)\r
+{\r
+    signed short dx, dy, x, y;\r
+    signed short xi, yi, d;\r
+    unsigned short i;\r
+    unsigned char c;\r
+\r
+    dx = x2 - x1;\r
+    dy = y2 - y1;\r
+    if(dx >= 0)\r
+    {\r
+        xi = 1;\r
+    } else {\r
+        xi = -1;\r
+        dx = -dx;\r
+    }\r
+    if(dy >= 0)\r
+    {\r
+        yi = 1;\r
+    } else {\r
+        yi = -1;\r
+        dy = -dy;\r
+    }\r
+    d = 0;\r
+    x = x1;\r
+    y = y1;\r
+    c = 0;\r
+    if(dx > dy)\r
+    {\r
+        for(i = 0; i <= dx; i++)\r
+        {\r
+            DBCopyBufferClip((unsigned short)x, (unsigned short)y, Buffer, w, h, 0);\r
+            d += dy;\r
+            if(d > dx)\r
+            {\r
+                d -= dx;\r
+                y += yi;\r
+            }\r
+            x += xi;\r
+        }\r
+    } else {\r
+        for(i = 0; i <= dy; i++)\r
+        {\r
+            DBCopyBufferClip((unsigned short)x, (unsigned short)y, Buffer, w, h, 0);\r
+            d += dx;\r
+            if(d > 0)\r
+            {\r
+                d -= dy;\r
+                x += xi;\r
+            }\r
+            y += yi;\r
+        }\r
+    }\r
+}\r
+\r
+void DBCopyBufferRotated(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, signed short rx, signed short ry, unsigned short a)\r
+{\r
+    signed short cx, cy, sx, sy, xd, yd;\r
+    unsigned long Data, OffsetMax;\r
+    signed long w1, h1;\r
+    signed long x0, y0, xn, yn;\r
+    signed long c, s;\r
+\r
+    c = (signed long)(Cosine[a] * 0x10000);\r
+    s = (signed long)(Sine[a] * 0x10000);\r
+    if(a < 90)\r
+    {\r
+        w1 = (s * h) + (c * w);\r
+        h1 = (c * h) + (s * w);\r
+        x0 = (signed long)((Sine[a] * Sine[a] * (float)w) * 0x10000);\r
+        y0 = (signed long)(-(Sine[a] * Cosine[a] * (float)w) * 0x10000);\r
+        xd = 0;\r
+        yd = (signed short)((s * (signed long)w) >> 16);\r
+    } else if(a < 180)\r
+    {\r
+        w1 = (s * h) - (c * w);\r
+        h1 = (s * w) - (c * h);\r
+        x0 = (signed long)((w - ((Sine[a] * Cosine[a]) * (float)h)) * 0x10000);\r
+        y0 = (signed long)((Cosine[a] * Cosine[a] * (float)h) * 0x10000);\r
+        xd = (signed short)((-c * (signed long)w) >> 16);\r
+        yd = (signed short)(h1 >> 16);\r
+    } else if(a < 270)\r
+    {\r
+        w1 = -(s * h) - (c * w);\r
+        h1 = -(s * w) - (c * h);\r
+        x0 = (signed long)((Cosine[a] * Cosine[a] * (float)w) * 0x10000);\r
+        y0 = (signed long)((h + (Sine[a] * Cosine[a] * (float)w)) * 0x10000);\r
+        xd = (signed short)(w1 >> 16);\r
+        yd = (signed short)((-c * (signed long)h) >> 16);\r
+    } else {\r
+        w1 = (c * w) - (s * h);\r
+        h1 = (c * h) - (s * w);\r
+        x0 = (signed long)((Sine[a] * Cosine[a] * (float)h) * 0x10000);\r
+        y0 = (signed long)((Sine[a] * Sine[a] * (float)h) * 0x10000);\r
+        xd = (signed short)((-s * (signed long)h) >> 16);\r
+        yd = 0;\r
+    }\r
+    if((w1 & 0xFFFF) != 0)\r
+        w1 = (w1 & 0xFFFF0000) + 0x10000;\r
+    if((h1 & 0xFFFF) != 0)\r
+        h1 = (h1 & 0xFFFF0000) + 0x10000;\r
+    w1 >>= 16;\r
+    h1 >>= 16;\r
+    xd += (signed short)(((c * (signed long)rx) + (s * (signed long)ry)) >> 16);\r
+    yd += (signed short)(((c * (signed long)ry) - (s * (signed long)ry)) >> 16);\r
+    sy = y - yd;\r
+    for(cy = 0; cy < h1; cy++)\r
+    {\r
+        xn = x0;\r
+        yn = y0;\r
+        sx = x - xd;\r
+        for(cx = 0; cx < w1; cx++)\r
+        {\r
+            if((xn >= 0) && (yn >= 0) && (xn < (w << 16)) && (yn < (h << 16)))\r
+            {\r
+                Data = ((unsigned long *)Buffer)[((xn & 0xFFFF0000) + ((yn & 0xFFFF0000) * w)) >> 16];\r
+                if(Data != bgc)\r
+                    DBPSetC(sx, sy, Data);\r
+                if((sx == x) && (sy == y))\r
+                    ((unsigned long *)Buffer)[((xn & 0xFFFF0000) + ((yn & 0xFFFF0000) * w)) >> 16] = MakeColor(255, 0, 0);\r
+            }\r
+            sx++;\r
+            xn += c;\r
+            yn += s;\r
+        }\r
+        x0 -= s;\r
+        y0 += c;\r
+        sy++;\r
+    }\r
+}\r
+\r
+void ColorAdd(unsigned long *Bg, unsigned long Amount)\r
+{\r
+    Color *c1;\r
+    Color c2;\r
+    unsigned short R, G, B;\r
+\r
+    c1 = (Color *)Bg;\r
+    c2 = *(Color *)&Amount;\r
+    R = (unsigned short)c1->R + (unsigned short)c2.R;\r
+    G = (unsigned short)c1->G + (unsigned short)c2.G;\r
+    B = (unsigned short)c1->B + (unsigned short)c2.B;\r
+    if(R > 255)\r
+        R = 255;\r
+    if(G > 255)\r
+        G = 255;\r
+    if(B > 255)\r
+        B = 255;\r
+    c1->R = (unsigned char)R;\r
+    c1->G = (unsigned char)G;\r
+    c1->B = (unsigned char)B;\r
+}\r
+\r
+void ColorSub(unsigned long *Bg, unsigned long Amount)\r
+{\r
+    Color *c1;\r
+    Color c2;\r
+    signed short R, G, B;\r
+\r
+    c1 = (Color *)Bg;\r
+    c2 = *(Color *)&Amount;\r
+    R = (unsigned short)c1->R - (unsigned short)c2.R;\r
+    G = (unsigned short)c1->G - (unsigned short)c2.G;\r
+    B = (unsigned short)c1->B - (unsigned short)c2.B;\r
+    if(R < 0)\r
+        R = 0;\r
+    if(G < 0)\r
+        G = 0;\r
+    if(B < 0)\r
+        B = 0;\r
+    c1->R = (unsigned char)R;\r
+    c1->G = (unsigned char)G;\r
+    c1->B = (unsigned char)B;\r
+}\r
+\r
+/*void ColorAdd(unsigned long *Bg, unsigned long Amount)\r
+{\r
+    asm("\r
+    movd %%eax, %%mm0\r
+    movd (%%esi), %%mm1\r
+    paddusb %%mm1, %%mm0\r
+    movd %%mm0, 0(%%esi)\r
+    "\r
+    :\r
+    : "a" (Amount), "S" (Bg)\r
+    );\r
+    asm("\r
+    addb %%al, 0(%%esi)\r
+    jnc ColorAddNoBlueOF\r
+    movb $0xFF, 0(%%esi)\r
+ColorAddNoBlueOF:\r
+    addb %%ah, 1(%%esi)\r
+    jnc ColorAddNoGreenOF\r
+    movb $0xFF, 1(%%esi)\r
+ColorAddNoGreenOF:\r
+    shrl $0x10, %%eax\r
+    addb %%al, 2(%%esi)\r
+    jnc ColorAddNoRedOF\r
+    movb $0xFF, 2(%%esi)\r
+ColorAddNoRedOF:\r
+    "\r
+    :\r
+    : "a" (Amount), "S" (Bg)\r
+    );\r
+}*/\r
+\r
+/*void ColorSub(unsigned long *Bg, unsigned long Amount)\r
+{\r
+    asm("\r
+    subb %%al, 0(%%esi)\r
+    jnc ColorSubNoBlueOF\r
+    movb $0x00, 0(%%esi)\r
+ColorSubNoBlueOF:\r
+    subb %%ah, 1(%%esi)\r
+    jnc ColorSubNoGreenOF\r
+    movb $0x00, 1(%%esi)\r
+ColorSubNoGreenOF:\r
+    shrl $0x10, %%eax\r
+    subb %%al, 2(%%esi)\r
+    jnc ColorSubNoRedOF\r
+    movb $0x00, 2(%%esi)\r
+ColorSubNoRedOF:\r
+    "\r
+    :\r
+    : "a" (Amount), "S" (Bg)\r
+    );\r
+}*/\r
+\r
+void ColorAvr(unsigned long *Bg, unsigned long Amount)\r
+{\r
+/*\r
+    asm("\r
+    addb %%al, 0(%%esi)\r
+    .byte 0xD0\r
+    .byte 0x1E\r
+    addb %%ah, 1(%%esi)\r
+    .byte 0xD0\r
+    .byte 0x5E\r
+    .byte 1\r
+    shrl $0x10, %%eax\r
+    addb %%al, 2(%%esi)\r
+    .byte 0xD0\r
+    .byte 0x5E\r
+    .byte 2\r
+    "\r
+    :\r
+    : "a" (Amount), "S" (Bg)\r
+    );\r
+*/\r
+    ((Color *)(Bg))->R = (unsigned char)(((unsigned short)((Color *)(Bg))->R + (unsigned short)(*(Color *)(&Amount)).R) >> 1);\r
+    ((Color *)(Bg))->G = (unsigned char)(((unsigned short)((Color *)(Bg))->G + (unsigned short)(*(Color *)(&Amount)).G) >> 1);\r
+    ((Color *)(Bg))->B = (unsigned char)(((unsigned short)((Color *)(Bg))->B + (unsigned short)(*(Color *)(&Amount)).B) >> 1);\r
+}\r
+\r
+void ColorSpc(unsigned long *Bg, unsigned long Amount)\r
+{\r
+    Color *c1;\r
+    Color c2;\r
+    unsigned short R, G, B;\r
+\r
+    c1 = (Color *)Bg;\r
+    c2 = *(Color *)&Amount;\r
+    R = ((3 * (unsigned short)c1->R) + (3 * (unsigned short)c2.R)) >> 2;\r
+    G = ((3 * (unsigned short)c1->G) + (3 * (unsigned short)c2.G)) >> 2;\r
+    B = ((3 * (unsigned short)c1->B) + (3 * (unsigned short)c2.B)) >> 2;\r
+    if(R > 255)\r
+        R = 255;\r
+    if(G > 255)\r
+        G = 255;\r
+    if(B > 255)\r
+        B = 255;\r
+    c1->R = (unsigned char)R;\r
+    c1->G = (unsigned char)G;\r
+    c1->B = (unsigned char)B;\r
+}\r
+\r
+void ColorFul(unsigned long *Bg, unsigned long Amount)\r
+{\r
+    Color *c1, c2;\r
+\r
+    *(unsigned long *)&c2 = Amount;\r
+    c1 = (Color *)Bg;\r
+    if(c2.R > c1->R)\r
+        c1->R = c2.R;\r
+    if(c2.G > c1->G)\r
+        c1->G = c2.G;\r
+    if(c2.B > c1->B)\r
+        c1->B = c2.B;\r
+}\r
+\r
+void DBCopyMapBufferClip(signed short x, signed short y, unsigned char *Buffer, unsigned char *BgBuffer, unsigned short w, unsigned short h)\r
+{\r
+    unsigned char *WorkOffset;\r
+    unsigned long OffsetAdd1, OffsetAdd2;\r
+    signed short cx, cy, sx, sy, cw, ch;\r
+    unsigned long data;\r
+\r
+    if((x > clip_x2) || ((x + w) < clip_x1) || (y > clip_y2) || ((y + h) < clip_y1))\r
+        return;\r
+    sx = (x < clip_x1)?(clip_x1 - x):0;\r
+    sy = (y < clip_y1)?(clip_y1 - y):0;\r
+    cw = (x + (signed short)w - 1 > clip_x2)?(clip_x2 - x + 1):(signed short)w;\r
+    ch = (y + (signed short)h - 1 > clip_y2)?(clip_y2 - y + 1):(signed short)h;\r
+    Buffer += (sx + (sy * w)) << 2;\r
+    BgBuffer += sx + (sy * w);\r
+    OffsetAdd1 = (sx + w - cw) << 2;\r
+    OffsetAdd2 = 1280 - ((cw - sx) << 2);\r
+    WorkOffset = DblBuffer + ((signed long)(y + sy) << 10) + ((signed long)(y + sy) << 8) + ((signed long)(x + sx) << 2);\r
+    for(cy = 0; cy < ch - sy; cy++)\r
+    {\r
+        for(cx = 0; cx < cw - sx; cx++)\r
+        {\r
+            data = *(unsigned long *)Buffer;\r
+            if(data != 0)\r
+            {\r
+                if(((*BgBuffer) & 0x70) == 0x20)\r
+                    ColorAdd((unsigned long *)WorkOffset, data);\r
+                else\r
+                    *(unsigned long *)WorkOffset = data;\r
+            }\r
+            Buffer += 4;\r
+            BgBuffer++;\r
+            WorkOffset += 4;\r
+        }\r
+        Buffer += OffsetAdd1;\r
+        BgBuffer += OffsetAdd1 >> 2;\r
+        WorkOffset += OffsetAdd2;\r
+    }\r
+}\r
+\r
+void DBCopyBufferTrans(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char Method)\r
+{\r
+    unsigned char *WorkOffset;\r
+    unsigned long OffsetAdd;\r
+    unsigned short cx, cy;\r
+    unsigned long data;\r
+\r
+    WorkOffset = DblBuffer + ((signed long)y << 10) + ((signed long)y << 8) + ((signed long)x << 2);\r
+    OffsetAdd = 1280 - (w << 2);\r
+    for(cy = 0; cy < h; cy++)\r
+    {\r
+        for(cx = 0; cx < w; cx++)\r
+        {\r
+            data = *(unsigned long *)Buffer;\r
+            if(data != bgc)\r
+                TransOps[Method]((unsigned long *)WorkOffset, data);\r
+            Buffer += 4;\r
+            WorkOffset += 4;\r
+        }\r
+        WorkOffset += OffsetAdd;\r
+    }\r
+}\r
+\r
+void DBCopyBufferClipTrans(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned short bgc, unsigned char Method)\r
+{\r
+    unsigned char *WorkOffset;\r
+    unsigned long OffsetAdd1, OffsetAdd2;\r
+    signed short cx, cy, sx, sy, cw, ch;\r
+    unsigned long data;\r
+\r
+    if((x > clip_x2) || ((x + w) < clip_x1) || (y > clip_y2) || ((y + h) < clip_y1))\r
+        return;\r
+    if((x >= clip_x1) && ((x + w) <= clip_x2) && (y >= clip_y1) && ((y + h) <= clip_y2))\r
+    {\r
+        DBCopyBufferTrans(x, y, Buffer, w, h, bgc, Method);\r
+        return;\r
+    }\r
+    sx = (x < clip_x1)?(clip_x1 - x):0;\r
+    sy = (y < clip_y1)?(clip_y1 - y):0;\r
+    cw = (x + (signed short)w - 1 > clip_x2)?(clip_x2 - x + 1):(signed short)w;\r
+    ch = (y + (signed short)h - 1 > clip_y2)?(clip_y2 - y + 1):(signed short)h;\r
+    Buffer += (sx + (sy * w)) << 2;\r
+    OffsetAdd1 = (sx + w - cw) << 2;\r
+    OffsetAdd2 = 1280 - ((cw - sx) << 2);\r
+    WorkOffset = DblBuffer + ((signed long)(y + sy) << 10) + ((signed long)(y + sy) << 8) + ((signed long)(x + sx) << 2);\r
+    for(cy = 0; cy < ch - sy; cy++)\r
+    {\r
+        for(cx = 0; cx < cw - sx; cx++)\r
+        {\r
+            data = *(unsigned long *)Buffer;\r
+            if(data != bgc)\r
+                TransOps[Method]((unsigned long *)WorkOffset, data);\r
+            Buffer += 4;\r
+            WorkOffset += 4;\r
+        }\r
+        Buffer += OffsetAdd1;\r
+        WorkOffset += OffsetAdd2;\r
+    }\r
+}\r
+\r
+void DBSpriteLineTrans(signed short x1, signed short y1, signed short x2, signed short y2, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned char Method)\r
+{\r
+    signed short dx, dy, x, y;\r
+    signed short xi, yi, d;\r
+    unsigned short i;\r
+    unsigned char c;\r
+\r
+    dx = x2 - x1;\r
+    dy = y2 - y1;\r
+    if(dx >= 0)\r
+    {\r
+        xi = 1;\r
+    } else {\r
+        xi = -1;\r
+        dx = -dx;\r
+    }\r
+    if(dy >= 0)\r
+    {\r
+        yi = 1;\r
+    } else {\r
+        yi = -1;\r
+        dy = -dy;\r
+    }\r
+    d = 0;\r
+    x = x1;\r
+    y = y1;\r
+    c = 0;\r
+    if(dx > dy)\r
+    {\r
+        for(i = 0; i <= dx; i++)\r
+        {\r
+            DBCopyBufferClipTrans((unsigned short)x, (unsigned short)y, Buffer, w, h, 0, Method);\r
+            d += dy;\r
+            if(d > dx)\r
+            {\r
+                d -= dx;\r
+                y += yi;\r
+            }\r
+            x += xi;\r
+        }\r
+    } else {\r
+        for(i = 0; i <= dy; i++)\r
+        {\r
+            DBCopyBufferClipTrans((unsigned short)x, (unsigned short)y, Buffer, w, h, 0, Method);\r
+            d += dx;\r
+            if(d > 0)\r
+            {\r
+                d -= dy;\r
+                x += xi;\r
+            }\r
+            y += yi;\r
+        }\r
+    }\r
+}\r
+\r
+void DBCopyBufferTransRotated(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char Method, signed short rx, signed short ry, unsigned short a)\r
+{\r
+    unsigned short cx, cy, sx, sy;\r
+    unsigned long Data, OffsetMax;\r
+    signed long w1, h1;\r
+    signed long x0, y0, xn, yn;\r
+    signed long c, s;\r
+\r
+    c = (signed long)(Cosine[a] * 0x10000);\r
+    s = (signed long)(Sine[a] * 0x10000);\r
+    w1 = (s * h) + (c * w);\r
+    h1 = (c * h) + (s * w);\r
+    x0 = (signed long)((Sine[a] * Sine[a] * (float)w) * 0x10000);\r
+    y0 = (signed long)(-(Sine[a] * Cosine[a] * (float)w) * 0x10000);\r
+    if((w1 & 0xFFFF) != 0)\r
+        w1 = (w1 & 0xFFFF0000) + 0x10000;\r
+    if((h1 & 0xFFFF) != 0)\r
+        h1 = (h1 & 0xFFFF0000) + 0x10000;\r
+    w1 >>= 16;\r
+    h1 >>= 16;\r
+    sx = x;\r
+    sy = y;\r
+    for(cy = 0; cy < h1; cy++)\r
+    {\r
+        xn = x0;\r
+        yn = y0;\r
+        for(cx = 0; cx < w1; cx++)\r
+        {\r
+            if((xn >= 0) && (yn >= 0) && (xn < (w << 16)) && (yn < (h << 16)))\r
+            {\r
+                Data = ((unsigned long *)Buffer)[((xn & 0xFFFF0000) + ((yn & 0xFFFF0000) * w)) >> 16];\r
+                if(Data != bgc)\r
+                    DBPSetCTrans(sx, sy, Data, Method);\r
+            }\r
+            sx++;\r
+            xn += c;\r
+            yn += s;\r
+        }\r
+        x0 -= s;\r
+        y0 += c;\r
+        sy++;\r
+        sx = x;\r
+    }\r
+}\r
+\r
+#undef MOTION_BLUR\r
+\r
+void DisplayDB(void)\r
+{\r
+    SDL_Flip(VBuffer);\r
+}\r
+\r
+#if 0\r
+void DisplayDB(void)\r
+{\r
+    unsigned long i;\r
+\r
+#ifdef DEBUG\r
+    return;\r
+#endif\r
+#ifndef MOTION_BLUR\r
+    if(BPP == 0x20)\r
+    {\r
+        /*for(i = 0; i < 256000; i += 4)\r
+        {\r
+            *(unsigned long *)&VBuffer[i] = SmoothColor(*(unsigned long *)&DblBuffer[i], *(unsigned long *)&DblBuffer[i - 1280], *(unsigned long *)&DblBuffer[i + 1280], *(unsigned long *)&DblBuffer[i - 4], *(unsigned long *)&DblBuffer[i + 4]);\r
+        }*/\r
+        /*for(i = 0; i < 64000; i++)\r
+            ((unsigned long *)VBuffer)[i] = ((unsigned long *)DblBuffer)[i];*/\r
+        DisplayDBAsm();\r
+        /*for(i = 0; i < 256000; i++)\r
+            _farpokeb(VideoLDT, i, DblBuffer[i]);*/\r
+    } else {\r
+        for(i = 0; i < 64000; i++)\r
+        {\r
+            VBuffer[i * 3] = (DblBuffer)[i * 4];\r
+            VBuffer[(i * 3) + 1] = (DblBuffer)[(i * 4) + 1];\r
+            VBuffer[(i * 3) + 2] = (DblBuffer)[(i * 4) + 2];\r
+        }\r
+    }\r
+#else\r
+    asm("\r
+    mov $0, %%eax\r
+    movd %%eax, %%mm2\r
+    "\r
+    :\r
+    :\r
+    : "%eax"\r
+    );\r
+    for(i = 0; i < 256000; i += 4)\r
+    {\r
+        asm("\r
+        movd (%%eax), %%mm0\r
+        movd (%%esi), %%mm1\r
+        punpcklbw %%mm2, %%mm0\r
+        punpcklbw %%mm2, %%mm1\r
+        paddw %%mm1, %%mm0\r
+        psrlw $1, %%mm0\r
+        packuswb %%mm0, %%mm0\r
+        movd %%mm0, (%%esi)\r
+        "\r
+        :\r
+        : "a" (DblBuffer + i), "S" (VBuffer + i)\r
+        );\r
+    }\r
+    asm("emms");\r
+#endif\r
+}\r
+#endif\r
diff --git a/dblbuf.h b/dblbuf.h
new file mode 100644 (file)
index 0000000..fb35424
--- /dev/null
+++ b/dblbuf.h
@@ -0,0 +1,26 @@
+void DBSetClip(signed short x1, signed short y1, signed short x2, signed short y2);\r
+unsigned long DBPoint(unsigned short x, unsigned short y);\r
+void DBPSet(unsigned short x, unsigned short y, unsigned long c);\r
+void DBPSetC(unsigned short x, unsigned short y, unsigned long c);\r
+void DBPSetCTrans(unsigned short x, unsigned short y, unsigned long c, unsigned char Method);\r
+void DBFPoly(signed short x1, signed short y1, signed short x2, signed short y2, signed short x3, signed short y3, unsigned long Color);\r
+void DBFPolyTrans(signed short x1, signed short y1, signed short x2, signed short y2, signed short x3, signed short y3, unsigned long Color, unsigned char Method);\r
+void DBFCircle(signed short x, signed short y, unsigned short r, unsigned long Color, unsigned char Filled, float Aspect);\r
+void DBFCircleTrans(signed short x, signed short y, unsigned short r, unsigned long Color, unsigned char Filled, float Aspect, unsigned char Method);\r
+void DBFCircleFadedTrans(signed short x, signed short y, unsigned short r, unsigned long Color, float Aspect, unsigned char Method);\r
+void DBFRect(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned long c);\r
+void DBFRectTrans(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned long c, unsigned char Method);\r
+void DBLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2);\r
+void DBSpriteLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned char *Buffer, unsigned short w, unsigned short h);\r
+void DBLineTrans(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2, unsigned char Method);\r
+void DBSpriteLineTrans(signed short x1, signed short y1, signed short x2, signed short y2, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned char Method);\r
+void DBCopyBuffer(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc);\r
+void DBCopyBufferClip(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc);\r
+void ColorAvr(unsigned long *Bg, unsigned long Amount);\r
+void ColorSpc(unsigned long *Bg, unsigned long Amount);\r
+void ColorFul(unsigned long *Bg, unsigned long Amount);\r
+void DBCopyBufferTrans(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char Method);\r
+void DBCopyBufferClipTrans(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned short bgc, unsigned char Method);\r
+void DisplayDB(void);\r
+void DBCopyBufferRotated(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, signed short rx, signed short ry, unsigned short a);\r
+void DBCopyBufferTransRotated(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char Method, signed short rx, signed short ry, unsigned short a);\r
diff --git a/executor.c b/executor.c
new file mode 100644 (file)
index 0000000..20607d3
--- /dev/null
@@ -0,0 +1,849 @@
+#include "dblbuf.h"\r
+#include "kvidha.h"\r
+#include "sb.h"\r
+\r
+unsigned long Color16To32(unsigned short c)\r
+{\r
+    Color Temp;\r
+\r
+    Temp.Reserved = 0;\r
+    Temp.R = (((c & 0xF800) >> 11) * 255) / 31;\r
+    Temp.G = (((c & 0x07E0) >> 5) * 255) / 63;\r
+    Temp.B = ((c & 0x001F) * 255) / 31;\r
+    return(*(unsigned long *)&Temp);\r
+}\r
+\r
+unsigned short Color32To16(unsigned long c)\r
+{\r
+    Color Temp;\r
+    unsigned short Result;\r
+\r
+    *(unsigned long *)&Temp = c;\r
+    Result = (((unsigned short)Temp.R * 31) / 255) << 11;\r
+    Result |= (((unsigned short)Temp.G * 63) / 255) << 5;\r
+    Result |= ((unsigned short)Temp.B * 31) / 255;\r
+    return(Result);\r
+}\r
+\r
+signed short GetArg(unsigned char *Code, unsigned short *Offset, signed short *Variables)\r
+{\r
+    unsigned char ArgType;\r
+    signed short Result;\r
+\r
+    ArgType = Code[*Offset];\r
+    switch(ArgType)\r
+    {\r
+        case 0:\r
+            Result = (signed short)((unsigned short)Code[*Offset + 1] + (unsigned short)(Code[*Offset + 2] << 8));\r
+            *Offset += 3;\r
+            break;\r
+        case 1:\r
+            Result = Regs[Code[*Offset + 1]];\r
+            *Offset += 2;\r
+            break;\r
+        case 2:\r
+            Result = Variables[Code[*Offset + 1]];\r
+            *Offset += 2;\r
+            break;\r
+    }\r
+    return(Result);\r
+}\r
+\r
+void Execute(unsigned char *WorkCode, signed short *Variables, unsigned short StartOffset)\r
+{\r
+    unsigned short Offset;\r
+    unsigned char Finished;\r
+    unsigned short DestroyObject;\r
+    unsigned short ObjectNum;\r
+    unsigned short SpriteNum;\r
+    unsigned short Instruction;\r
+    signed short Damage, Damage2;\r
+    signed short x, y, x2, y2, xv, yv;\r
+    signed short Data, Data2, Angle;\r
+    unsigned short dx, dy;\r
+    unsigned char Frame;\r
+    unsigned char Smokes;\r
+    unsigned short Max;\r
+    unsigned char Register, Player, Reg2, Reg3, Reg4, Reg5, Reg6;\r
+    unsigned char Data3, Data4;\r
+    unsigned short Color;\r
+    unsigned short i;\r
+    unsigned char DisplayInfo;\r
+    unsigned char Choice;\r
+    unsigned short LocalStackPos;\r
+    unsigned long Misc;\r
+    float Data5, Data6;\r
+    static unsigned short DbgPtr = 0;\r
+\r
+    Finished = 0;\r
+    DisplayInfo = 1;\r
+    Choice = 0;\r
+    Offset = StartOffset;\r
+    LocalStackPos = 0;\r
+    while(Finished == 0)\r
+    {\r
+        if((DebugMode == 1) && (DisplayInfo == 1))\r
+        {\r
+            for(i = 0; i < NumClasses; i++)\r
+            {\r
+                if(WorkCode == Classes[i]->Code)\r
+                    break;\r
+            }\r
+            DBFRect(33, 58, 287, 142, MakeColor(0, 255, 0));\r
+            DBFRect(34, 59, 286, 141, MakeColor(0, 0, 0));\r
+            Data = sprintf(TextBuffer, "Debugging!\n\n\rClass: %u\n\rOffset: %u\n\n\rCode dump:\n\r", i, Offset);\r
+            for(y = 0; y < 2; y++)\r
+            {\r
+                for(x = 0; x < 15; x++)\r
+                {\r
+                    Data += sprintf(TextBuffer + Data, " %02X", WorkCode[Offset + x + (y * 15)]);\r
+                }\r
+                Data += sprintf(TextBuffer + Data, "\n\r");\r
+            }\r
+            sprintf(TextBuffer + Data, "\0");\r
+            DBPrint(TextBuffer, 35, 60, 255);\r
+            Data = sprintf(TextBuffer, "Register dump:\n\r");\r
+            for(y = 0; y < 4; y++)\r
+            {\r
+                for(x = 0; x < 8; x++)\r
+                {\r
+                    Data += sprintf(TextBuffer + Data, " %-6i", Regs[x + (y * 8)]);\r
+                }\r
+                Data += sprintf(TextBuffer + Data, "\n\r");\r
+            }\r
+            sprintf(TextBuffer + Data, "\0");\r
+            DBPrint(TextBuffer, 35, 105, 255);\r
+            DisplayDB();\r
+            while(KeyTable[57] == 0)\r
+            {\r
+               GetEvents();\r
+                if(KeyTable[203] == 1)\r
+                {\r
+                    if(Choice > 0)\r
+                        Choice--;\r
+                    while(KeyTable[203] == 1)\r
+                       GetEvents();\r
+                }\r
+                if(KeyTable[205] == 1)\r
+                {\r
+                    if(Choice < 2)\r
+                        Choice++;\r
+                    while(KeyTable[205] == 1)\r
+                       GetEvents();\r
+                }\r
+                sprintf(TextBuffer, " %cStep       %cRun to return      %cComplete\0", (unsigned short)(Choice == 0)?45:32, (unsigned short)(Choice == 1)?45:32, (unsigned short)(Choice == 2)?45:32);\r
+                DBPrint(TextBuffer, 35, 135, 255);\r
+                DisplayDB();\r
+            }\r
+            while(KeyTable[57] == 1)\r
+               GetEvents();\r
+            if(Choice == 1)\r
+                DisplayInfo = 2;\r
+            if(Choice == 2)\r
+                DisplayInfo = 0;\r
+        }\r
+        Instruction = (unsigned short)WorkCode[Offset] + ((unsigned short)WorkCode[Offset + 1] << 8);\r
+        Offset += 2;\r
+        switch(Instruction)\r
+        {\r
+            case 0:                                 //Return\r
+                if(DisplayInfo == 2)\r
+                    DisplayInfo = 1;\r
+                if(LocalStackPos == 0)\r
+                {\r
+                    Finished = 1;\r
+                } else {\r
+                    Offset = Stack[--StackPos];\r
+                    LocalStackPos--;\r
+                }\r
+                break;\r
+            case 1:                                 //DestroyObject\r
+                DestroyObject = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                RemoveHitTest(DestroyObject);\r
+                if(Objects[DestroyObject]->SpriteLink != 0xFFFF)\r
+                    Sprites[Objects[DestroyObject]->SpriteLink]->Used = 0;\r
+                Objects[DestroyObject]->SpriteLink = 0xFFFF;\r
+                Objects[DestroyObject]->Used = 2;\r
+                break;\r
+            case 2:                                 //SpawnExplosion\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Frame = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Smokes = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                SpawnExplosion(x, y, Frame, Smokes, (unsigned char)Data);\r
+                break;\r
+            case 3:                                 //StoreRandom\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Max = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = rand() % Max;\r
+                break;\r
+            case 4:                                 //StoreReg\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Data;\r
+                break;\r
+            case 5:                                 //Add\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Data + Data2;\r
+                break;\r
+            case 6:                                 //Equals\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = (Data == Data2)?1:0;\r
+                break;\r
+            case 7:                                 //If\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data != 0)\r
+                    Offset = Data2;\r
+                break;\r
+            case 8:                                 //SpawnPixel\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                xv = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                yv = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Player = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Damage = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Color = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                SpawnPixel((unsigned short)x, (unsigned short)y, (float)xv / 100, (float)yv / 100, Player, (unsigned char)Data, (unsigned char)Data2, Damage, Color16To32(Color));\r
+                break;\r
+            case 9:                                 //NotEquals\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = (Data != Data2)?1:0;\r
+                break;\r
+            case 10:                                //Substract\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Data - Data2;\r
+                break;\r
+            case 11:                                //SpawnObject\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                xv = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                yv = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                SpawnObject((unsigned short)Data, (unsigned char)Data2, (unsigned short)x, (unsigned short)y, (float)xv / 100, (float)yv / 100);\r
+                break;\r
+            case 12:                                //Goto\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Offset = Data;\r
+                break;\r
+            case 13:                                //StoreVariable\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Variables[Data] = Data2;\r
+                break;\r
+            case 14:                                //GetLevelInfo\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) Regs[Register] = LevelWidth;\r
+                if(Data == 1) Regs[Register] = LevelHeight;\r
+                if(Data == 2) Regs[Register] = (signed short)LevelFinished;\r
+                if(Data == 3) Regs[Register] = (signed short)GameType;\r
+                if(Data == 4) Regs[Register] = (signed short)((Gravity + 0.005) * 100);\r
+                break;\r
+            case 15:                                //SetPlayerInfo\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Player = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) Players[Player]->Object = (unsigned short)Data2;\r
+                if(Data == 1) Players[Player]->VPObject = (unsigned short)Data2;\r
+                if(Data == 2) Players[Player]->Used = (unsigned char)Data2;\r
+                if(Data == 3) Players[Player]->Angle = (float)Data2;\r
+                if(Data == 4) Players[Player]->Dir = (unsigned char)Data2;\r
+                if(Data == 5) Players[Player]->CrossColor = (unsigned long)Color16To32(Data2);\r
+                if(Data == 6) Players[Player]->Left = (unsigned char)Data2;\r
+                if(Data == 7) Players[Player]->Right = (unsigned char)Data2;\r
+                if(Data == 8) Players[Player]->Up = (unsigned char)Data2;\r
+                if(Data == 9) Players[Player]->Down = (unsigned char)Data2;\r
+                if(Data == 10) Players[Player]->Shoot = (unsigned char)Data2;\r
+                if(Data == 11) Players[Player]->Change = (unsigned char)Data2;\r
+                if(Data == 13) Players[Player]->Health = (unsigned short)Data2;\r
+                if(Data == 14) Players[Player]->MaxHealth = (unsigned short)Data2;\r
+                if(Data == 15) Players[Player]->Kills = Data2;\r
+                if(Data == 16) Players[Player]->Lives = Data2;\r
+                if(Data == 18) Players[Player]->JustShot = (unsigned char)Data2;\r
+                if(Data == 18) Players[Player]->CurWeapon = Data2;\r
+                break;\r
+            case 16:                                //GetPlayerInfo\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Player = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) Regs[Register] = (signed short)Players[Player]->Object;\r
+                if(Data == 1) Regs[Register] = (signed short)Players[Player]->VPObject;\r
+                if(Data == 2) Regs[Register] = (signed short)Players[Player]->Used;\r
+                if(Data == 3) Regs[Register] = (signed short)Players[Player]->Angle;\r
+                if(Data == 4) Regs[Register] = (signed short)Players[Player]->Dir;\r
+                if(Data == 5) Regs[Register] = (signed short)Players[Player]->CrossColor;\r
+                if(Data == 6) Regs[Register] = (signed short)Players[Player]->Left;\r
+                if(Data == 7) Regs[Register] = (signed short)Players[Player]->Right;\r
+                if(Data == 8) Regs[Register] = (signed short)Players[Player]->Up;\r
+                if(Data == 9) Regs[Register] = (signed short)Players[Player]->Down;\r
+                if(Data == 10) Regs[Register] = (signed short)Players[Player]->Shoot;\r
+                if(Data == 11) Regs[Register] = (signed short)Players[Player]->Change;\r
+                if(Data == 12)\r
+                {\r
+                    Angle = Players[Player]->Angle;\r
+                    if(Angle > 90)\r
+                        Angle -= 360;\r
+                    if(Players[Player]->Dir == 1)\r
+                        Angle = 180 - Angle;\r
+                    if(Angle < 0)\r
+                        Angle += 360;\r
+                    Regs[Register] = Angle;\r
+                }\r
+                if(Data == 13) Regs[Register] = (signed short)Players[Player]->Health;\r
+                if(Data == 14) Regs[Register] = (signed short)Players[Player]->MaxHealth;\r
+                if(Data == 15) Regs[Register] = (signed short)Players[Player]->Kills;\r
+                if(Data == 16) Regs[Register] = (signed short)Players[Player]->Lives;\r
+                if(Data == 17) Regs[Register] = (signed short)Players[Player]->JustShot;\r
+                if(Data == 18) Regs[Register] = (signed short)Players[Player]->CurWeapon;\r
+                break;\r
+            case 17:                                //SetObjectInfo\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                ObjectNum = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) Objects[ObjectNum]->x = (float)Data2;\r
+                if(Data == 1) Objects[ObjectNum]->y = (float)Data2;\r
+                if(Data == 2) Objects[ObjectNum]->xv = (float)Data2 / 100;\r
+                if(Data == 3) Objects[ObjectNum]->yv = (float)Data2 / 100;\r
+                if(Data == 4) Objects[ObjectNum]->SpriteLink = (unsigned short)Data2;\r
+                if(Data == 5) Objects[ObjectNum]->Owner = (unsigned char)Data2;\r
+                if(Data == 6) Objects[ObjectNum]->Class = (unsigned short)Data2;\r
+                if(Data == 7) Objects[ObjectNum]->Used = (unsigned char)Data2;\r
+                if(Data == 8) Objects[ObjectNum]->xv = (float)(signed short)Objects[ObjectNum]->xv + ((float)Data2 / 10000);\r
+                if(Data == 9) Objects[ObjectNum]->yv = (float)(signed short)Objects[ObjectNum]->yv + ((float)Data2 / 10000);\r
+                break;\r
+            case 18:                                //GetObjectInfo\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                ObjectNum = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) Regs[Register] = (signed short)Objects[ObjectNum]->x;\r
+                if(Data == 1) Regs[Register] = (signed short)Objects[ObjectNum]->y;\r
+                if(Data == 2) Regs[Register] = (signed short)(Objects[ObjectNum]->xv * 100);\r
+                if(Data == 3) Regs[Register] = (signed short)(Objects[ObjectNum]->yv * 100);\r
+                if(Data == 4) Regs[Register] = (signed short)Objects[ObjectNum]->SpriteLink;\r
+                if(Data == 5) Regs[Register] = (signed short)Objects[ObjectNum]->Owner;\r
+                if(Data == 6) Regs[Register] = (signed short)Objects[ObjectNum]->Class;\r
+                if(Data == 7) Regs[Register] = (signed short)Objects[ObjectNum]->Used;\r
+                if(Data == 8) Regs[Register] = (signed short)((Objects[ObjectNum]->xv - (float)(signed short)Objects[ObjectNum]->xv) * 10000);\r
+                if(Data == 9) Regs[Register] = (signed short)((Objects[ObjectNum]->yv - (float)(signed short)Objects[ObjectNum]->yv) * 10000);\r
+                break;\r
+            case 19:                                //ChangeSign\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = -Data;\r
+                break;\r
+            case 20:                                //Multiply\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Data * Data2;\r
+                break;\r
+            case 21:                                //Divide\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Data / Data2;\r
+                break;\r
+            case 22:                                //Call\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(StackPos < MAX_STACK)\r
+                {\r
+                    Stack[StackPos++] = Offset;\r
+                    LocalStackPos++;\r
+                    Offset = Data;\r
+                } else {\r
+                    sprintf(TextBuffer, "Stack overflow!\n\n\n\rPress space to continue...\0");\r
+                    DBFRect(68, 88, 252, 112, MakeColor(255, 0, 0));\r
+                    DBFRect(69, 89, 251, 111, MakeColor(0, 0, 0));\r
+                    DBPrint(TextBuffer, 70, 90, 255);\r
+                    DisplayDB();\r
+                    while(KeyTable[57] == 1)\r
+                       GetEvents();\r
+                    while(KeyTable[57] == 0)\r
+                       GetEvents();\r
+                }\r
+                break;\r
+            case 23:                                //SetSpriteInfo\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                SpriteNum = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if((unsigned short)SpriteNum == 0xFFFF)\r
+                    break;\r
+                if(Data == 0) Sprites[SpriteNum]->CurFrame = (unsigned char)Data2;\r
+                if(Data == 1) Sprites[SpriteNum]->AnimTimer = (unsigned char)Data2;\r
+                if(Data == 2) Sprites[SpriteNum]->AnimDelay = (unsigned char)Data2;\r
+                if(Data == 3) Sprites[SpriteNum]->Transparent = (unsigned char)Data2;\r
+                if(Data == 4) Sprites[SpriteNum]->x = (signed short)Data2;\r
+                if(Data == 5) Sprites[SpriteNum]->y = (signed short)Data2;\r
+                break;\r
+            case 24:                                //GetSpriteInfo\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                SpriteNum = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if((unsigned short)SpriteNum == 0xFFFF)\r
+                    break;\r
+                if(Data == 0) Regs[Register] = (signed short)Sprites[SpriteNum]->CurFrame;\r
+                if(Data == 1) Regs[Register] = (signed short)Sprites[SpriteNum]->AnimTimer;\r
+                if(Data == 2) Regs[Register] = (signed short)Sprites[SpriteNum]->AnimDelay;\r
+                if(Data == 3) Regs[Register] = (signed short)Sprites[SpriteNum]->Transparent;\r
+                if(Data == 4) Regs[Register] = (signed short)Sprites[SpriteNum]->x;\r
+                if(Data == 5) Regs[Register] = (signed short)Sprites[SpriteNum]->y;\r
+                if(Data == 6) Regs[Register] = (signed short)Sprites[SpriteNum]->Template;\r
+                break;\r
+            case 25:                                //GreaterThan\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = (Data > Data2)?1:0;\r
+                break;\r
+            case 26:                                //LessThan\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = (Data < Data2)?1:0;\r
+                break;\r
+            case 27:                                //GetKey\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Players[Data]->Keys[Data2];\r
+                break;\r
+            case 28:                                //CalcSine\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data < 0)\r
+                    Data += ((unsigned short)(-Data / 360) + 1) * 360;\r
+                if(Data >= 360)\r
+                    Data -= (unsigned short)(Data / 360) * 360;\r
+                Regs[Register] = Sine[Data] * 100;\r
+                break;\r
+            case 29:                                //CalcCosine\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data < 0)\r
+                    Data += ((unsigned short)(-Data / 360) + 1) * 360;\r
+                if(Data >= 360)\r
+                    Data -= (unsigned short)(Data / 360) * 360;\r
+                Regs[Register] = Cosine[Data] * 100;\r
+                break;\r
+            case 30:                                //GetPixelInfo\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) Regs[Register] = (signed short)Color32To16(GetMapPixel((unsigned short)x, (unsigned short)y, 0));\r
+                if(Data == 1) Regs[Register] = (signed short)GetMapPixel((unsigned short)x, (unsigned short)y, 1);\r
+                break;\r
+            case 31:                                //And\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Data & Data2;\r
+                break;\r
+            case 32:                                //Or\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Data | Data2;\r
+                break;\r
+            case 33:                                //BNot\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = !Data;\r
+                break;\r
+            case 34:                                //Not\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = ~Data;\r
+                break;\r
+            case 35:                                //DrawLine\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data4 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                DrawLine(x, y, x2, y2, Color16To32(Data), Color16To32(Data2), Data3, Data4);\r
+                break;\r
+            case 36:                                //StorePVar\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Player = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Players[Player]->PVars[Data] = Data2;\r
+                break;\r
+            case 37:                                //GetPVar\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Player = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Players[Player]->PVars[Data];\r
+                break;\r
+            case 38:                                //CalcDist\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Misc = ((unsigned long)(x - x2) * (unsigned long)(x - x2)) + ((unsigned long)(y - y2) * (unsigned long)(y - y2));\r
+                Regs[Register] = sqrt((double)Misc);\r
+                break;\r
+            case 39:                                //CalcAngle\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = CalcAngle(x, y, x2, y2);\r
+                break;\r
+            case 40:                                //AddHitTest\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                AddHitTest((unsigned short)Data);\r
+                break;\r
+            case 41:                                //RemoveHitTest\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                RemoveHitTest((unsigned short)Data);\r
+                break;\r
+            case 42:                                //CopyToMap\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Frame = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data4 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                CopyToMap(x - Caches[Data]->cx[Frame], y - Caches[Data]->cy[Frame], Caches[Data]->Frames[Frame], Caches[Data]->w, Caches[Data]->h, 0, Data3, Data4, (unsigned short)Data2);\r
+                break;\r
+            case 43:                                //HurtRadius\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Damage = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Damage2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Player = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                HurtRadius(x, y, Damage, Damage2, (unsigned short)Data, (unsigned short)Data2, Player);\r
+                break;\r
+            case 44:                                //CollVel\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data5 = ((float)GetArg(WorkCode, (unsigned short *)&Offset, Variables)) / 100;\r
+                Data6 = ((float)GetArg(WorkCode, (unsigned short *)&Offset, Variables)) / 100;\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                CollVel(x, y, (float *)&Data5, (float *)&Data6, Data3);\r
+                Regs[Data] = (signed short)(Data5 * 100);\r
+                Regs[Data2] = (signed short)(Data6 * 100);\r
+                break;\r
+            case 45:                                //SetObjectVar\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Objects[Data]->Variables[Data3] = Data2;\r
+                break;\r
+            case 46:                                //GetObjectVar\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = Objects[Data]->Variables[Data3];\r
+                break;\r
+            case 47:                                //Debug\r
+                DebugMode = 1;\r
+                break;\r
+            case 48:                                //Trace\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg2 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg4 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg5 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg6 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data4 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = -1;\r
+                Regs[Register] = CollisionTest((signed short *)&x, (signed short *)&y, (signed short *)&x2, (signed short *)&y2, Data3, Data4, (unsigned short *)&Data, 0xFF, 0);\r
+                Regs[Reg2] = x;\r
+                Regs[Reg3] = y;\r
+                Regs[Reg4] = x2;\r
+                Regs[Reg5] = y2;\r
+                Regs[Reg6] = Data;\r
+                break;\r
+            case 49:                                //CallExternal\r
+                ObjectNum = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Execute(Classes[Objects[ObjectNum]->Class]->Code, (signed short *)&Objects[ObjectNum]->Variables[0], Classes[Objects[ObjectNum]->Class]->Scripts[Data]);\r
+                break;\r
+            case 50:                                //SetLevelInfo\r
+                Data = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) LevelWidth = Data2;\r
+                if(Data == 1) LevelHeight = Data2;\r
+                if(Data == 2) LevelFinished = (unsigned short)Data2;\r
+                if(Data == 3) GameType = (unsigned char)Data2;\r
+                if(Data == 4) Gravity = (float)Data2 / 100;\r
+                break;\r
+            case 51:                                //SpawnSprite\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                xv = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                yv = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data4 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = SpawnSprite((unsigned char)Data, x, y, (signed char)xv, (signed char)yv, Data2, Data3, Data4);\r
+                break;\r
+            case 52:                                //Proximity\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = -1;\r
+                for(i = 0; i < MAX_HITTESTS; i++)\r
+                {\r
+                    if((ObjectNum = HitTests[i]) == 0xFFFF)\r
+                        break;\r
+                    if((x >= Objects[ObjectNum]->x - Data) && (x <= Objects[ObjectNum]->x + Data) && (y >= Objects[ObjectNum]->y - Data) && (y <= Objects[ObjectNum]->y + Data))\r
+                    {\r
+                        Misc = ((unsigned long)(x - (signed short)Objects[ObjectNum]->x) * (unsigned long)(x - (signed short)Objects[ObjectNum]->x)) + ((unsigned long)(y - (signed short)Objects[ObjectNum]->y) * (unsigned long)(y - (signed short)Objects[ObjectNum]->y));\r
+                        if((signed short)sqrt((double)Misc) <= Data)\r
+                        {\r
+                            Regs[Register] = ObjectNum;\r
+                            break;\r
+                        }\r
+                    }\r
+                }\r
+                break;\r
+            case 53:                                //PlaySound\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                PlaySound((unsigned short)Data, (unsigned char)Data2, 0, MAX_SOUNDS - 1, 22050, 1);\r
+                break;\r
+            case 54:                                //MakeColor\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg2 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg4 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = (Reg2 << 11) + (Reg3 << 5) + Reg4;\r
+                break;\r
+            case 55:                                //SetPixelInfo\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                SetMapPixel((unsigned short)x, (unsigned short)y, (Data == 0)?Color16To32(Data2):Data2, Data);\r
+                break;\r
+            case 56:                                //ExtProximity\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Max = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = -1;\r
+                for(i = 0; i < MAX_HITTESTS; i++)\r
+                {\r
+                    if((ObjectNum = HitTests[i]) == 0xFFFF)\r
+                        break;\r
+                    if((ObjectNum == Max) || (Objects[ObjectNum]->Class == (unsigned short)Data2))\r
+                        continue;\r
+                    if((x >= Objects[ObjectNum]->x - Data) && (x <= Objects[ObjectNum]->x + Data) && (y >= Objects[ObjectNum]->y - Data) && (y <= Objects[ObjectNum]->y + Data))\r
+                    {\r
+                        Misc = ((unsigned long)(x - (signed short)Objects[ObjectNum]->x) * (unsigned long)(x - (signed short)Objects[ObjectNum]->x)) + ((unsigned long)(y - (signed short)Objects[ObjectNum]->y) * (unsigned long)(y - (signed short)Objects[ObjectNum]->y));\r
+                        if((signed short)sqrt((double)Misc) <= Data)\r
+                        {\r
+                            Regs[Register] = ObjectNum;\r
+                            break;\r
+                        }\r
+                    }\r
+                }\r
+                break;\r
+            case 57:                                //DrawLightning\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                DrawLightning(x, y, x2, y2, Data, Data3);\r
+                break;\r
+            case 58:                                //PlaySoundLoop\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Misc = (unsigned long)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data5 = (float)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = (signed short)PlaySound((unsigned short)Data, (unsigned char)Data2, 0, MAX_SOUNDS - 1, Misc * 10, Data5 / 100);\r
+                break;\r
+            case 59:                                //SetSoundInfo\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) Sounds[Data3].Pitch = (unsigned long)Data2 * 10;\r
+                if(Data == 1) Sounds[Data3].Playing = (unsigned char)Data2;\r
+                if(Data == 2) Sounds[Data3].Volume = (float)(Data2 / 100);\r
+                break;\r
+            case 60:                                //GetSoundInfo\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data == 0) Regs[Register] = (signed short)(Sounds[Data3].Pitch / 10);\r
+                if(Data == 1) Regs[Register] = (signed short)Sounds[Data3].Playing;\r
+                if(Data == 2) Regs[Register] = (signed short)(Sounds[Data3].Volume * 100);\r
+                break;\r
+            case 61:                                //TraceCoords\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg2 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data4 = 0;\r
+                if(x2 > x)\r
+                {\r
+                    xv = 1;\r
+                    dx = x2 - x;\r
+                } else {\r
+                    xv = -1;\r
+                    dx = x - x2;\r
+                }\r
+                if(y2 > y)\r
+                {\r
+                    yv = 1;\r
+                    dy = y2 - y;\r
+                } else {\r
+                    yv = -1;\r
+                    dy = y - y2;\r
+                }\r
+                Max = 0;\r
+                if(dx > dy)\r
+                {\r
+                    for(i = 0; i <= dx; i++)\r
+                    {\r
+                        Regs[Register] = x;\r
+                        Regs[Reg2] = y;\r
+                        if(++Data4 >= Data3)\r
+                        {\r
+                            Execute(WorkCode, Variables, Data);\r
+                            Data4 = 0;\r
+                        }\r
+                        GetNextLineCoord(&x, &y, &Max, dx, dy, xv, yv);\r
+                    }\r
+                } else {\r
+                    for(i = 0; i <= dy; i++)\r
+                    {\r
+                        Regs[Register] = x;\r
+                        Regs[Reg2] = y;\r
+                        if(++Data4 >= Data3)\r
+                        {\r
+                            Execute(WorkCode, Variables, Data);\r
+                            Data4 = 0;\r
+                        }\r
+                        GetNextLineCoord(&x, &y, &Max, dx, dy, xv, yv);\r
+                    }\r
+                }\r
+                break;\r
+            case 62:                                //DecodeColor\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg2 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                i = (unsigned short)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = (i & 0xF800) >> 11;\r
+                Regs[Reg2] = (i & 0x07E0) >> 5;\r
+                Regs[Reg3] = i & 0x001F;\r
+                break;\r
+            case 63:                                //DrawPoly\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Color = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                DrawPoly(x, y, x2, y2, Data, Data2, Color16To32(Color), Data3);\r
+                break;\r
+            case 64:                                //LoopHitTests\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg2 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Reg3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                for(i = 0; i < MAX_HITTESTS; i++)\r
+                {\r
+                    if(HitTests[i] == 0xFFFF)\r
+                        break;\r
+                    Regs[Register] = HitTests[i];\r
+                    Regs[Reg2] = (signed short)Objects[HitTests[i]]->x;\r
+                    Regs[Reg3] = (signed short)Objects[HitTests[i]]->y;\r
+                    Execute(WorkCode, Variables, Data);\r
+                }\r
+                break;\r
+            case 65:                                //DrawCircle\r
+                x = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                y = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                x2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Color = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data3 = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                DrawCircle(x, y, x2, Color16To32(Color), Data3);\r
+                break;\r
+            case 66:                                //Sqrt\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data < 0)\r
+                    Data = 0;\r
+                Regs[Register] = (unsigned short)sqrt((float)Data);\r
+                break;\r
+            case 67:                                //Abs\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                if(Data < 0)\r
+                    Regs[Register] = -Data;\r
+                else\r
+                    Regs[Register] = Data;\r
+                break;\r
+            case 68:                                //StoreGVar\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data2 = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                GameVars[Data] = Data2;\r
+                break;\r
+            case 69:                                //GetGVar\r
+                Register = (unsigned char)GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Data = GetArg(WorkCode, (unsigned short *)&Offset, Variables);\r
+                Regs[Register] = GameVars[Data];\r
+                break;\r
+            case 70:                                //CondDebug\r
+                if(KeyTable[68] == 1)\r
+                    DebugMode = 1;\r
+                break;\r
+            default:\r
+                sprintf(TextBuffer, "Unknown instruction %u at offset %u!\n\rCode address: %p\n\n\rPress space to continue...\0", Instruction, Offset, (void *)WorkCode);\r
+                DBFRect(68, 88, 252, 112, MakeColor(255, 0, 0));\r
+                DBFRect(69, 89, 251, 111, MakeColor(0, 0, 0));\r
+                DBPrint(TextBuffer, 70, 90, 255);\r
+                DisplayDB();\r
+                while(KeyTable[57] == 1)\r
+                   GetEvents();\r
+                while(KeyTable[57] == 0)\r
+                   GetEvents();\r
+        }\r
+    }\r
+}\r
diff --git a/executor.h b/executor.h
new file mode 100644 (file)
index 0000000..cddee18
--- /dev/null
@@ -0,0 +1,2 @@
+signed short GetArg(unsigned char *Code, unsigned short *Offset, signed short *Variables);\r
+void Execute(unsigned char *WorkCode, signed short *Variables, unsigned short StartOffset);\r
diff --git a/fileio.c b/fileio.c
new file mode 100644 (file)
index 0000000..d507ce5
--- /dev/null
+++ b/fileio.c
@@ -0,0 +1,523 @@
+#include <stdio.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#define DAT_START 7\r
+\r
+typedef struct KvidFileType\r
+{\r
+    FILE *FilePtr;\r
+    unsigned char AtEOF;\r
+    struct KvidFileType *Parent;\r
+    unsigned char DataFile;\r
+    unsigned char ReSeek;\r
+    unsigned char CanWrite;\r
+    unsigned long CurFAT;\r
+    unsigned long CurAU;\r
+    unsigned short Offset;\r
+    unsigned short AUSize;\r
+    unsigned char LastOp;\r
+    unsigned char CurBit, CurChar;\r
+} KvidFile;\r
+\r
+KvidFile *MainDat;\r
+\r
+static unsigned long GetFAT(KvidFile *FileStr, unsigned long AU)\r
+{\r
+    unsigned long CurFAT, i, TargetFAT;\r
+\r
+    CurFAT = 0;\r
+    TargetFAT = AU / ((FileStr->AUSize >> 2) - 1);\r
+    for(i = 0; i < TargetFAT; i++)\r
+    {\r
+        fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize), SEEK_SET);\r
+        fread((void *)&CurFAT, 4, 1, FileStr->FilePtr);\r
+    }\r
+    return(CurFAT);\r
+}\r
+\r
+static void SetFATEntry(KvidFile *FileStr, unsigned long AU, unsigned long Entry)\r
+{\r
+    unsigned long CurFAT, i, TargetFAT;\r
+\r
+    CurFAT = 0;\r
+    TargetFAT = AU / ((FileStr->AUSize >> 2) - 1);\r
+    for(i = 0; i < TargetFAT; i++)\r
+    {\r
+        fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize), SEEK_SET);\r
+        fread((void *)&CurFAT, 4, 1, FileStr->FilePtr);\r
+        if(CurFAT >= 0x80000000)\r
+               return;\r
+    }\r
+    fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize) + (((AU % ((FileStr->AUSize >> 2) - 1)) + 1) << 2), SEEK_SET);\r
+    fwrite((void *)&Entry, 4, 1, FileStr->FilePtr);\r
+}\r
+\r
+static unsigned long FindFreeAU(KvidFile *FileStr, unsigned char InhibitCreation)\r
+{\r
+       unsigned long OldFAT, CurFAT, NumEntries, Entry, i, FATNum;\r
+\r
+    CurFAT = 0;\r
+    FATNum = 0;\r
+    NumEntries = (FileStr->AUSize >> 2) - 1;\r
+    while(CurFAT < 0x80000000)\r
+    {\r
+       OldFAT = CurFAT;\r
+        fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize), SEEK_SET);\r
+        fread((void *)&CurFAT, 4, 1, FileStr->FilePtr);\r
+        for(i = 0; i < NumEntries; i++)\r
+        {\r
+               fread((void *)&Entry, 4, 1, FileStr->FilePtr);\r
+            if(Entry == 0)\r
+               return((FATNum * NumEntries) + i);\r
+        }\r
+        FATNum++;\r
+    }\r
+    if(InhibitCreation == 1)\r
+       return(0xFFFFFFFF);\r
+    fseek(FileStr->FilePtr, DAT_START + (OldFAT * FileStr->AUSize), SEEK_SET);\r
+    CurFAT = NumEntries * FATNum;\r
+       fwrite((void *)&CurFAT, 4, 1, FileStr->FilePtr);\r
+    fseek(FileStr->FilePtr, DAT_START + (CurFAT * FileStr->AUSize), SEEK_SET);\r
+    Entry = 0xFFFFFFFF;\r
+    fwrite((void *)&Entry, 4, 1, FileStr->FilePtr);\r
+    Entry = 0;\r
+    for(i = 0; i < NumEntries; i++)\r
+    {\r
+       fwrite((void *)&Entry, 4, 1, FileStr->FilePtr);\r
+    }\r
+    SetFATEntry(FileStr, CurFAT, 0xFFFFFFFE);\r
+    return(FindFreeAU(FileStr, 1));\r
+}\r
+\r
+static unsigned char GetDatChar(KvidFile *FileStr)\r
+{\r
+    unsigned char RetVal;\r
+    unsigned short OldAU;\r
+    unsigned short NumEntries;\r
+    KvidFile *CurFile;\r
+\r
+    for(CurFile = FileStr->Parent; CurFile != NULL; CurFile = CurFile->Parent)\r
+        CurFile->ReSeek = 1;\r
+    if(FileStr->ReSeek == 1)\r
+    {\r
+        fseek(FileStr->FilePtr, DAT_START + (FileStr->CurAU * FileStr->AUSize) + FileStr->Offset, SEEK_SET);\r
+        FileStr->ReSeek = 0;\r
+        FileStr->CurFAT = 0xFFFFFFFF;\r
+    }\r
+    RetVal = (unsigned char)fgetc(FileStr->FilePtr);\r
+    if(FileStr->Offset++ == FileStr->AUSize - 1)\r
+    {\r
+        if(FileStr->CurFAT == 0xFFFFFFFF)\r
+            FileStr->CurFAT = GetFAT(FileStr, FileStr->CurAU);\r
+        OldAU = FileStr->CurAU;\r
+        fseek(FileStr->FilePtr, DAT_START + (FileStr->CurFAT * FileStr->AUSize) + (((FileStr->CurAU % ((FileStr->AUSize >> 2) - 1)) + 1) << 2), SEEK_SET);\r
+        fread((void *)&FileStr->CurAU, 4, 1, FileStr->FilePtr);\r
+        if(FileStr->CurAU == 0xFFFFFFFF)\r
+            FileStr->AtEOF = 1;\r
+        FileStr->Offset = 0;\r
+        NumEntries = (FileStr->AUSize >> 2) - 1;\r
+        if((FileStr->CurAU / NumEntries) == (OldAU / NumEntries))\r
+        {\r
+            fseek(FileStr->FilePtr, DAT_START + (FileStr->CurAU * FileStr->AUSize) + FileStr->Offset, SEEK_SET);\r
+        } else {\r
+            FileStr->ReSeek = 1;\r
+        }\r
+    }\r
+    return(RetVal);\r
+}\r
+\r
+static void PutDatChar(unsigned char c, KvidFile *FileStr)\r
+{\r
+    unsigned char RetVal;\r
+    unsigned long OldAU;\r
+    KvidFile *CurFile;\r
+\r
+    for(CurFile = FileStr->Parent; CurFile != NULL; CurFile = CurFile->Parent)\r
+        CurFile->ReSeek = 1;\r
+    if(FileStr->ReSeek == 1)\r
+    {\r
+        fseek(FileStr->FilePtr, DAT_START + (FileStr->CurAU * FileStr->AUSize) + FileStr->Offset, SEEK_SET);\r
+        FileStr->ReSeek = 0;\r
+        FileStr->CurFAT = 0xFFFFFFFF;\r
+    }\r
+    fputc(c, FileStr->FilePtr);\r
+    if(FileStr->Offset++ == FileStr->AUSize - 1)\r
+    {\r
+        if(FileStr->CurFAT == 0xFFFFFFFF)\r
+            FileStr->CurFAT = GetFAT(FileStr, FileStr->CurAU);\r
+        fseek(FileStr->FilePtr, DAT_START + (FileStr->CurFAT * FileStr->AUSize) + (((FileStr->CurAU % ((FileStr->AUSize >> 2) - 1)) + 1) << 2), SEEK_SET);\r
+        OldAU = FileStr->CurAU;\r
+        fread((void *)&FileStr->CurAU, 4, 1, FileStr->FilePtr);\r
+        if(FileStr->CurAU == 0xFFFFFFFF)\r
+        {\r
+               FileStr->CurAU = FindFreeAU(FileStr, 0);\r
+            SetFATEntry(FileStr, OldAU, FileStr->CurAU);\r
+            SetFATEntry(FileStr, FileStr->CurAU, 0xFFFFFFFF);\r
+        }\r
+        FileStr->Offset = 0;\r
+        FileStr->ReSeek = 1;\r
+    }\r
+}\r
+\r
+unsigned char FileGetChar(KvidFile *FileStr)\r
+{\r
+    signed long RetVal;\r
+\r
+    if(FileStr->AtEOF == 1)\r
+        return(0);\r
+    if(FileStr->LastOp == 1)\r
+    {\r
+       FileStr->LastOp = 0;\r
+        fflush(FileStr->FilePtr);\r
+    }\r
+    if(FileStr->Parent != NULL)\r
+        return(GetDatChar(FileStr));\r
+    if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))\r
+    {\r
+        if((RetVal = (signed long)fgetc(FileStr->FilePtr)) == EOF)\r
+        {\r
+            FileStr->AtEOF = 1;\r
+            return(0);\r
+        } else {\r
+            return((unsigned char)RetVal);\r
+        }\r
+    }\r
+    if((FileStr->Parent == NULL) && (FileStr->DataFile == 1))\r
+        return(GetDatChar(FileStr));\r
+}\r
+\r
+void FilePutChar(unsigned char c, KvidFile *FileStr)\r
+{\r
+    if(FileStr->CanWrite == 0)\r
+       return;\r
+       FileStr->LastOp = 1;\r
+    if(FileStr->Parent != NULL)\r
+        PutDatChar(c, FileStr);\r
+    if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))\r
+       fputc(c, FileStr->FilePtr);\r
+    if((FileStr->Parent == NULL) && (FileStr->DataFile == 1))\r
+        PutDatChar(c, FileStr);\r
+}\r
+\r
+void FileSkip(KvidFile *FileStr, unsigned long NumBytes)\r
+{\r
+       KvidFile *CurFile;\r
+\r
+    if(FileStr->AtEOF == 1)\r
+       return;\r
+       if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))\r
+    {\r
+       fseek(FileStr->FilePtr, NumBytes, SEEK_CUR);\r
+        return;\r
+    }\r
+    for(CurFile = FileStr->Parent; CurFile != NULL; CurFile = CurFile->Parent)\r
+        CurFile->ReSeek = 1;\r
+    if(FileStr->ReSeek == 1)\r
+        FileStr->CurFAT = 0xFFFFFFFF;\r
+    while((NumBytes > 0) && (FileStr->AtEOF == 0))\r
+    {\r
+       if(NumBytes < FileStr->AUSize - FileStr->Offset)\r
+           {\r
+               if(FileStr->ReSeek == 0)\r
+               fseek(FileStr->FilePtr, NumBytes, SEEK_CUR);\r
+            FileStr->Offset += NumBytes;\r
+            NumBytes = 0;\r
+        } else {\r
+            NumBytes -= FileStr->AUSize - FileStr->Offset;\r
+               if(FileStr->CurFAT == 0xFFFFFFFF)\r
+                   FileStr->CurFAT = GetFAT(FileStr, FileStr->CurAU);\r
+               fseek(FileStr->FilePtr, DAT_START + (FileStr->CurFAT * FileStr->AUSize) + (((FileStr->CurAU % ((FileStr->AUSize >> 2) - 1)) + 1) << 2), SEEK_SET);\r
+               fread((void *)&FileStr->CurAU, 4, 1, FileStr->FilePtr);\r
+               if(FileStr->CurAU == 0xFFFFFFFF)\r
+                   FileStr->AtEOF = 1;\r
+               FileStr->Offset = 0;\r
+               FileStr->ReSeek = 1;\r
+           }\r
+    }\r
+    if(FileStr->ReSeek == 1)\r
+    {\r
+        fseek(FileStr->FilePtr, DAT_START + (FileStr->CurAU * FileStr->AUSize) + FileStr->Offset, SEEK_SET);\r
+        FileStr->ReSeek = 0;\r
+        FileStr->CurFAT = 0xFFFFFFFF;\r
+    }\r
+}\r
+\r
+unsigned long FileReadBits(unsigned char NumBits, KvidFile *FileStr)\r
+{\r
+    unsigned char i;\r
+    unsigned long Value;\r
+\r
+    Value = 0;\r
+    for(i = NumBits; i > 0; i--)\r
+    {\r
+        if(FileStr->CurBit > 7)\r
+        {\r
+            FileStr->CurChar = fgetc(FileStr->FilePtr);\r
+            FileStr->CurBit = 7;\r
+        }\r
+        if((FileStr->CurChar & (1 << FileStr->CurBit)) != 0)\r
+            Value += 1 << (i - 1);\r
+        FileStr->CurBit--;\r
+    }\r
+    return(Value);\r
+}\r
+\r
+void FileRead(void *Buffer, unsigned long NumBytes, KvidFile *FileStr)\r
+{\r
+       if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))\r
+    {\r
+        fread(Buffer, NumBytes, 1, FileStr->FilePtr);\r
+        return;\r
+    }\r
+    while(NumBytes-- > 0)\r
+       *(unsigned char *)Buffer++ = FileGetChar(FileStr);\r
+}\r
+\r
+void FileWrite(void *Buffer, unsigned long NumBytes, KvidFile *FileStr)\r
+{\r
+       if(FileStr->CanWrite == 0)\r
+       return;\r
+       if((FileStr->Parent == NULL) && (FileStr->DataFile == 0))\r
+    {\r
+        fwrite(Buffer, NumBytes, 1, FileStr->FilePtr);\r
+        return;\r
+    }\r
+    while(NumBytes-- > 0)\r
+       FilePutChar(*(unsigned char *)Buffer++, FileStr);\r
+}\r
+\r
+void FileClose(KvidFile *FileStr)\r
+{\r
+       if(FileStr->Parent == NULL)\r
+       fclose(FileStr->FilePtr);\r
+}\r
+\r
+unsigned char OpenRootDir(KvidFile *FileStr, KvidFile *ParentFile)\r
+{\r
+       if(ParentFile->DataFile == 0)\r
+       return(0);\r
+       FileStr->DataFile = 0;\r
+       FileStr->CanWrite = ParentFile->CanWrite;\r
+    FileStr->Parent = ParentFile;\r
+    FileStr->FilePtr = ParentFile->FilePtr;\r
+    FileStr->AtEOF = 0;\r
+    FileStr->LastOp = 0;\r
+    FileStr->ReSeek = 1;\r
+    FileStr->CurAU = 1;\r
+    FileStr->Offset = 0;\r
+    FileStr->AUSize = ParentFile->AUSize;\r
+    FileStr->CurBit = 255;\r
+    return(1);\r
+}\r
+\r
+unsigned char OpenNestedFile(unsigned char *FileName, KvidFile *FileStr, KvidFile *ParentFile, unsigned long *TimeBuffer)\r
+{\r
+       unsigned char FileNameBuffer[20];\r
+    KvidFile RootDir;\r
+\r
+    if(OpenRootDir(&RootDir, ParentFile) == 0)\r
+       return(0);\r
+    FileStr->DataFile = 0;\r
+    FileStr->CanWrite = ParentFile->CanWrite;\r
+    FileStr->Parent = ParentFile;\r
+    FileStr->FilePtr = ParentFile->FilePtr;\r
+    FileStr->AtEOF = 0;\r
+    FileStr->LastOp = 0;\r
+    FileStr->ReSeek = 1;\r
+    FileStr->Offset = 0;\r
+    FileStr->AUSize = ParentFile->AUSize;\r
+    FileStr->CurBit = 255;\r
+    while(1)\r
+    {\r
+        FileRead((void *)FileNameBuffer, 20, &RootDir);\r
+        if((FileNameBuffer[0] == 0) || (RootDir.AtEOF == 1))\r
+            return(0);\r
+        if(strcmp(FileNameBuffer, FileName) == 0)\r
+        {\r
+               FileRead((void *)FileNameBuffer, 4, &RootDir);\r
+            FileNameBuffer[4] = 0;\r
+            if(TimeBuffer == NULL)\r
+                       FileSkip(&RootDir, 4);\r
+            else\r
+               FileRead((void *)TimeBuffer, 4, &RootDir);\r
+            FileRead((void *)&FileStr->CurAU, 4, &RootDir);\r
+            if(strcmp(FileNameBuffer, "SDIR") == 0)\r
+            {\r
+               FileRead((void *)FileNameBuffer, 5, FileStr);\r
+                FileNameBuffer[5] = 0;\r
+                if(strcmp(FileNameBuffer, "KFDAT") != 0)\r
+                       return(0);\r
+                FileRead((void *)&FileStr->AUSize, 2, FileStr);\r
+               FileStr->DataFile = 1;\r
+            }\r
+            return(1);\r
+        } else {\r
+            FileSkip(&RootDir, 12);\r
+        }\r
+    }\r
+}\r
+\r
+unsigned char OpenFile(unsigned char *FileName, KvidFile *FileStr)\r
+{\r
+    FileStr->DataFile = 0;\r
+    FileStr->Parent = NULL;\r
+    FileStr->AtEOF = 0;\r
+    FileStr->LastOp = 0;\r
+    FileStr->CurBit = 255;\r
+    if((FileStr->FilePtr = fopen(FileName, "rb+")) == NULL)\r
+    {\r
+        if((FileStr->FilePtr = fopen(FileName, "rb")) == NULL)\r
+            return((MainDat == NULL)?0:OpenNestedFile(FileName, FileStr, MainDat, NULL));\r
+        else\r
+            FileStr->CanWrite = 0;\r
+    } else {\r
+        FileStr->CanWrite = 1;\r
+    }\r
+    return(1);\r
+}\r
+\r
+unsigned char DeleteFile(unsigned char *FileName, KvidFile *ParentFile)\r
+{\r
+       unsigned char FileNameBuffer[20];\r
+    unsigned short OldOffset;\r
+    unsigned long OldAU, CurAU, CurFAT;\r
+    KvidFile RootDir;\r
+\r
+    if(OpenRootDir(&RootDir, ParentFile) == 0)\r
+       return(0);\r
+    while(1)\r
+    {\r
+        OldOffset = RootDir.Offset;\r
+        OldAU = RootDir.CurAU;\r
+        FileRead((void *)FileNameBuffer, 20, &RootDir);\r
+        if((FileNameBuffer[0] == 0) || (RootDir.AtEOF == 1))\r
+            return(0);\r
+        if(strcmp(FileNameBuffer, FileName) == 0)\r
+        {\r
+               FileSkip(&RootDir, 8);\r
+            FileRead(&CurAU, 4, &RootDir);\r
+               RootDir.Offset = OldOffset;\r
+            RootDir.CurAU = OldAU;\r
+            RootDir.ReSeek = 1;\r
+            FilePutChar(1, &RootDir);\r
+            while(CurAU < 0x80000000)\r
+            {\r
+               CurFAT = GetFAT(&RootDir, CurAU);\r
+                fseek(RootDir.FilePtr, DAT_START + (CurFAT * RootDir.AUSize) + ((CurAU % ((RootDir.AUSize >> 2) - 1)) << 2) + 4, SEEK_SET);\r
+                OldAU = CurAU;\r
+                fread((void *)&CurAU, 4, 1, RootDir.FilePtr);\r
+                fseek(RootDir.FilePtr, DAT_START + (CurFAT * RootDir.AUSize) + ((OldAU % ((RootDir.AUSize >> 2) - 1)) << 2) + 4, SEEK_SET);\r
+                CurFAT = 0;\r
+                fwrite((void *)&CurFAT, 4, 1, RootDir.FilePtr);\r
+            }\r
+            return(1);\r
+        } else {\r
+            FileSkip(&RootDir, 12);\r
+        }\r
+    }\r
+}\r
+\r
+unsigned char CreateFile(unsigned char *FileName, KvidFile *FileStr, KvidFile *ParentFile, unsigned long FileType)\r
+{\r
+       KvidFile RootDir;\r
+    unsigned char FileNameBuffer[20];\r
+    unsigned char Existing;\r
+    unsigned long OldAU;\r
+    unsigned short OldOffset;\r
+    unsigned long i;\r
+    unsigned long CurTime;\r
+    unsigned long NewAU;\r
+\r
+       if(ParentFile == NULL)\r
+    {\r
+       FileStr->DataFile = 0;\r
+        FileStr->Parent = NULL;\r
+        FileStr->AtEOF = 1;\r
+        FileStr->LastOp = 0;\r
+        FileStr->CanWrite = 1;\r
+        if((FileStr->FilePtr = fopen(FileName, "wb+")) == NULL)\r
+               return(0);\r
+        else\r
+               return(1);\r
+    }\r
+    if((OpenRootDir(&RootDir, ParentFile) == 0) || (RootDir.CanWrite == 0))\r
+       return(0);\r
+    FileStr->DataFile = 0;\r
+    FileStr->CanWrite = ParentFile->CanWrite;\r
+    FileStr->Parent = ParentFile;\r
+    FileStr->FilePtr = ParentFile->FilePtr;\r
+    FileStr->AtEOF = 0;\r
+    FileStr->LastOp = 0;\r
+    FileStr->ReSeek = 1;\r
+    FileStr->Offset = 0;\r
+    FileStr->AUSize = ParentFile->AUSize;\r
+    FileStr->CurBit = 255;\r
+    while(1)\r
+    {\r
+       OldAU = RootDir.CurAU;\r
+        OldOffset = RootDir.Offset;\r
+        FileRead((void *)FileNameBuffer, 20, &RootDir);\r
+        if(((Existing = FileNameBuffer[0]) < 2) || (RootDir.AtEOF == 1))\r
+        {\r
+               RootDir.CurAU = OldAU;\r
+            RootDir.Offset = OldOffset;\r
+            RootDir.ReSeek = 1;\r
+            for(i = 0; FileName[i] != 0; i++)\r
+               FileNameBuffer[i] = FileName[i];\r
+            while(i < 20)\r
+               FileNameBuffer[i++] = 0;\r
+            FileWrite((void *)FileNameBuffer, 20, &RootDir);\r
+            FileWrite((void *)&FileType, 4, &RootDir);\r
+            CurTime = (unsigned long)time(NULL);\r
+            FileWrite((void *)&CurTime, 4, &RootDir);\r
+            NewAU = FindFreeAU(ParentFile, 0);\r
+            SetFATEntry(ParentFile, NewAU, 0xFFFFFFFF);\r
+            RootDir.ReSeek = 1;\r
+            FileWrite((void *)&NewAU, 4, &RootDir);\r
+            if(Existing == 0)\r
+                   for(i = 0; i < 32; i++)\r
+                       FilePutChar(0, &RootDir);\r
+            FileStr->CurAU = NewAU;\r
+            return(1);\r
+        }\r
+        FileSkip(&RootDir, 12);\r
+    }\r
+}\r
+\r
+unsigned char OpenDatFile(unsigned char *FileName, KvidFile *FileStr)\r
+{\r
+       unsigned char Signature[6];\r
+    FileStr->DataFile = 1;\r
+    FileStr->Parent = NULL;\r
+    FileStr->ReSeek = 0;\r
+    FileStr->AtEOF = 0;\r
+    FileStr->LastOp = 0;\r
+    FileStr->CurBit = 255;\r
+    if((FileStr->FilePtr = fopen(FileName, "rb+")) == NULL)\r
+    {\r
+        if((FileStr->FilePtr = fopen(FileName, "rb")) == NULL)\r
+            return(0);\r
+        else\r
+            FileStr->CanWrite = 0;\r
+    } else {\r
+        FileStr->CanWrite = 1;\r
+    }\r
+    fread((void *)Signature, 1, 5, FileStr->FilePtr);\r
+    Signature[5] = 0;\r
+    if(strcmp(Signature, "KFDAT") != 0)\r
+    {\r
+       fclose(FileStr->FilePtr);\r
+        return(0);\r
+    }\r
+    fread((void *)&FileStr->AUSize, 2, 1, FileStr->FilePtr);\r
+    if((FileStr->AUSize % 4) != 0)\r
+    {\r
+       fclose(FileStr->FilePtr);\r
+        return(0);\r
+    }\r
+    FileStr->CurFAT = 0;\r
+    FileStr->CurAU = 0;\r
+    FileStr->Offset = 0;\r
+    return(1);\r
+}\r
diff --git a/fileio.h b/fileio.h
new file mode 100644 (file)
index 0000000..5b1f061
--- /dev/null
+++ b/fileio.h
@@ -0,0 +1,36 @@
+#ifndef fileio_h\r
+#define fileio_h\r
+\r
+typedef struct KvidFileType\r
+{\r
+    FILE *FilePtr;\r
+    unsigned char AtEOF;\r
+    struct KvidFileType *Parent;\r
+    unsigned char DataFile;\r
+    unsigned char ReSeek;\r
+    unsigned char CanWrite;\r
+    unsigned long CurFAT;\r
+    unsigned long CurAU;\r
+    unsigned short Offset;\r
+    unsigned short AUSize;\r
+    unsigned char LastOp;\r
+    unsigned char CurBit, CurChar;\r
+} KvidFile;\r
+\r
+extern KvidFile *MainDat;\r
+\r
+unsigned char FileGetChar(KvidFile *FileStr);\r
+void FilePutChar(unsigned char c, KvidFile *FileStr);\r
+void FileSkip(KvidFile *FileStr, unsigned long NumBytes);\r
+void FileRead(void *Buffer, unsigned long NumBytes, KvidFile *FileStr);\r
+void FileWrite(void *Buffer, unsigned long NumBytes, KvidFile *FileStr);\r
+void FileClose(KvidFile *FileStr);\r
+unsigned char OpenRootDir(KvidFile *FileStr, KvidFile *ParentFile);\r
+unsigned char OpenNestedFile(unsigned char *FileName, KvidFile *FileStr, KvidFile *ParentFile, unsigned long *TimeBuffer);\r
+unsigned char OpenFile(unsigned char *FileName, KvidFile *FileStr);\r
+unsigned char DeleteFile(unsigned char *FileName, KvidFile *ParentFile);\r
+unsigned char CreateFile(unsigned char *FileName, KvidFile *FileStr, KvidFile *ParentFile, unsigned long FileType);\r
+unsigned char OpenDatFile(unsigned char *FileName, KvidFile *FileStr);\r
+unsigned long FileReadBits(unsigned char NumBits, KvidFile *FileStr);\r
+\r
+#endif\r
diff --git a/kvidha.c b/kvidha.c
new file mode 100644 (file)
index 0000000..2423470
--- /dev/null
+++ b/kvidha.c
@@ -0,0 +1,4555 @@
+#include <stdio.h>\r
+#include <memory.h>\r
+#include <malloc.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <math.h>\r
+#include <dirent.h>\r
+#include <SDL/SDL.h>\r
+\r
+#include "fileio.h"\r
+\r
+#define NUM_KEYS 9\r
+#define MAX_STACK 4096\r
+#define MAX_LINES 1000\r
+#define NUM_MASKS 1\r
+#define MAX_PIXELS 5000\r
+#define NUM_COLORS 256\r
+#define NUM_PLANES 2\r
+#define MAX_SOUNDS 64\r
+#define MAX_RASTERS 100\r
+#define NUM_SCRIPTS 5\r
+#define MAX_SPRITES 5000\r
+#define MAX_PLAYERS 16\r
+#define MAX_OBJECTS 3000\r
+#define NUM_WEAPONS 55\r
+#define MAX_SAMPLES 31\r
+#define MAX_OBJLISTS 16\r
+#define MAX_HITTESTS 100\r
+#define MAX_CHANNELS 12\r
+#define MAX_PATTERNS 128\r
+#define MAX_MENUITEMS 128\r
+#define SB_SIZE 1024\r
+#define PLAY_TIME 0\r
+#define SHOW_MAP 1\r
+#define CP_BLUR 0\r
+\r
+#define MAP_SHOOTABLE 1\r
+#define MAP_WALKABLE 2\r
+#define MAP_DESTROYABLE 4\r
+#define MAP_TEMPORARY 8\r
+\r
+typedef struct ColorType\r
+{\r
+    unsigned char B;\r
+    unsigned char G;\r
+    unsigned char R;\r
+    unsigned char Reserved;\r
+} Color;\r
+\r
+typedef struct PixelType\r
+{\r
+    float x;\r
+    float y;\r
+    float xv;\r
+    float yv;\r
+    unsigned long c;\r
+    unsigned char SetColor;\r
+    unsigned char Explode;\r
+    signed short Damage;\r
+    unsigned char Owner;\r
+    unsigned char Used;\r
+} Pixel;\r
+\r
+typedef struct CacheType\r
+{\r
+    unsigned short w;\r
+    unsigned short h;\r
+    unsigned char NumFrames;\r
+    unsigned char **Frames;\r
+    signed short *cx;\r
+    signed short *cy;\r
+    unsigned char AnimDelay;\r
+} Cache;\r
+\r
+typedef struct SpriteType\r
+{\r
+    signed short x;\r
+    signed short y;\r
+    signed char xv;\r
+    signed char yv;\r
+    unsigned char AnimCount;\r
+    unsigned char AnimTimer;\r
+    unsigned char AnimDelay;\r
+    unsigned char CurFrame;\r
+    unsigned char Template;\r
+    unsigned char Transparent;\r
+    unsigned char Used;\r
+} Sprite;\r
+\r
+typedef struct WeaponType\r
+{\r
+    unsigned short Class;\r
+    unsigned short ReloadDelay;\r
+    unsigned short FireDelay;\r
+    unsigned short Ammo;\r
+    unsigned short MaxClips;\r
+    unsigned long Name;\r
+    unsigned short NameLength;\r
+} Weapon;\r
+\r
+typedef struct PWeaponType\r
+{\r
+    unsigned short Weapon;\r
+    unsigned short ReloadTimer;\r
+    unsigned short FireTimer;\r
+    unsigned short AmmoLeft;\r
+    unsigned short NumClips;\r
+    signed short Vars[4];\r
+    unsigned char Used;\r
+} PWeapon;\r
+\r
+typedef struct PlayerType\r
+{\r
+    unsigned char Visual;\r
+    unsigned short VPointX1;\r
+    unsigned short VPointY1;\r
+    unsigned short VPointX2;\r
+    unsigned short VPointY2;\r
+    unsigned short AMeterX1;\r
+    unsigned short AMeterY1;\r
+    unsigned short AMeterX2;\r
+    unsigned short AMeterY2;\r
+    unsigned short LMeterX1;\r
+    unsigned short LMeterY1;\r
+    unsigned short LMeterX2;\r
+    unsigned short LMeterY2;\r
+    unsigned short lx, ly;\r
+    unsigned short kx, ky;\r
+    unsigned short cx, cy;\r
+    unsigned short Object;\r
+    unsigned short VPObject;\r
+    unsigned char Keys[NUM_KEYS];\r
+    unsigned char HeldKeys[NUM_KEYS];\r
+    unsigned short KeyCodes[NUM_KEYS];\r
+    unsigned char Left;\r
+    unsigned char Right;\r
+    unsigned char Up;\r
+    unsigned char Down;\r
+    unsigned char Change;\r
+    unsigned char Shoot;\r
+    unsigned char JustShot;\r
+    signed short CurWeapon;\r
+    float Angle;\r
+    float AngleVel;\r
+    unsigned char Dir;\r
+    unsigned long CrossColor;\r
+    signed short Kills;\r
+    signed short Lives;\r
+    signed short Health;\r
+    signed short MaxHealth;\r
+    signed short PVars[40];\r
+    struct MaskType\r
+    {\r
+        unsigned char *Buffer;\r
+        unsigned char Method;\r
+        unsigned char Effects[16];\r
+    } Masks[NUM_MASKS];\r
+    unsigned char Used;\r
+} Player;\r
+\r
+typedef struct ClassType\r
+{\r
+    unsigned char *Code;\r
+    unsigned short Scripts[NUM_SCRIPTS];\r
+    unsigned char TickDelay;\r
+    unsigned char Sprite;\r
+    unsigned char StartFrame;\r
+    unsigned char RunHitTests;\r
+    unsigned char TouchDelay;\r
+    unsigned char TransSprite;\r
+    signed short GravityMod;\r
+} Class;\r
+\r
+typedef struct ObjectType\r
+{\r
+    float x;\r
+    float y;\r
+    float xv;\r
+    float yv;\r
+    unsigned short Class;\r
+    unsigned char TickTimer;\r
+    signed short Variables[6];\r
+    unsigned short SpriteLink;\r
+    unsigned char TouchTimer;\r
+    unsigned char Owner;\r
+    unsigned char Used;\r
+} Object;\r
+\r
+typedef struct ObjectListType\r
+{\r
+    struct\r
+    {\r
+        unsigned short Object;\r
+        signed short x1, y1, x2, y2;\r
+    } Objects[MAX_OBJECTS + 1];\r
+    unsigned short NumObjects;\r
+    unsigned char Used;\r
+} ObjectList;\r
+\r
+typedef struct LineType\r
+{\r
+    signed short x1, y1;\r
+    signed short x2, y2;\r
+    unsigned long c1, c2;\r
+    unsigned short Transparent;\r
+    unsigned char UseSprite;\r
+    unsigned char AnimTimer;\r
+    unsigned char CurFrame;\r
+    unsigned char Used;\r
+} Line;\r
+\r
+typedef struct RasterType\r
+{\r
+    signed short x1, y1;\r
+    signed short x2, y2;\r
+    signed short x3, y3;\r
+    unsigned long Color;\r
+    unsigned char Transparent;\r
+    unsigned char Type;\r
+    unsigned char Used;\r
+} Raster;\r
+\r
+typedef struct PalType\r
+{\r
+    unsigned char r;\r
+    unsigned char g;\r
+    unsigned char b;\r
+} Pal;\r
+\r
+typedef struct SoundCacheType\r
+{\r
+    unsigned char *SoundBuffer;\r
+    unsigned long Length;\r
+} SoundCache;\r
+\r
+typedef struct SoundType\r
+{\r
+    unsigned short Sound;\r
+    unsigned char Playing;\r
+    unsigned char Repeat;\r
+    float Volume;\r
+    unsigned long Offset;\r
+    unsigned long Pitch;\r
+    unsigned long PitchError;\r
+} Sound;\r
+\r
+typedef struct ModSampleType\r
+{\r
+    unsigned long SampleLen;\r
+    unsigned char FineTune;\r
+    unsigned char Volume;\r
+    unsigned long LoopStart;\r
+    unsigned long LoopLen;\r
+    unsigned char Allocated;\r
+    signed char *Buffer;\r
+} ModSample;\r
+\r
+typedef struct ModChannelType\r
+{\r
+    unsigned short Period;\r
+    unsigned short CurPeriod;\r
+    unsigned short OldPeriod;\r
+    unsigned char Volume;\r
+    unsigned char CurVolume;\r
+    unsigned char Sample;\r
+    unsigned long Offset;\r
+    signed char LastSample;\r
+    unsigned char Looping;\r
+    unsigned char Playing;\r
+    unsigned long Reminder;\r
+    unsigned char Effect;\r
+    unsigned char Oscillation;\r
+    unsigned char OscAmp;\r
+    unsigned char OscFreq;\r
+    float OscOffset;\r
+    unsigned char OscWave;\r
+    unsigned char OscNoTrig;\r
+    union\r
+    {\r
+        struct TwinNibbleType\r
+        {\r
+            unsigned char n1 : 4;\r
+            unsigned char n2 : 4;\r
+        } Nibbles;\r
+        unsigned char b;\r
+    } EffectData;\r
+} ModChannel;\r
+\r
+typedef struct ModEventType\r
+{\r
+    unsigned short Period;\r
+    unsigned char Sample;\r
+    unsigned char Effect;\r
+    unsigned char EffectData;\r
+} ModEvent;\r
+\r
+struct CodeType\r
+{\r
+    signed short Parent, Size;\r
+    signed long Value;\r
+} Codes[4096];\r
+\r
+void SetMapPixel(unsigned short x, unsigned short y, unsigned long c, unsigned short Handle);\r
+unsigned long GetMapPixel(unsigned short x, unsigned short y, unsigned short Handle);\r
+void ShowMap(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned short MapX, unsigned short MapY);\r
+void SetMode(unsigned char Mode);\r
+unsigned char SeekData(unsigned char *ID);\r
+unsigned char LoadSprite(unsigned char *ID, unsigned short CacheNum);\r
+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 Transparent);\r
+unsigned char Init(unsigned short *Result);\r
+void Terminate(void);\r
+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 long c);\r
+void ControlSprites(void);\r
+void ControlPixels(void);\r
+unsigned char ArgExist(unsigned short argc, unsigned char **argv, char *Match);\r
+void CopyToMap(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char ColorPattern, unsigned char DestroyAll, unsigned short Attributes);\r
+void SpawnExplosion(signed short x, signed short y, unsigned char StartFrame, unsigned char Smokes, unsigned char Sound);\r
+unsigned short SpawnObject(unsigned short Class, unsigned char Owner, unsigned short x, unsigned short y, float xv, float yv);\r
+void ControlObjects(void);\r
+unsigned short WallAngle(unsigned short x, unsigned short y);\r
+void GetInputs(void);\r
+void DBPrint(unsigned char *Buffer, signed short x, signed short y, unsigned char bgc);\r
+void FontPrint(unsigned char *Buffer, signed short sx, signed short y, unsigned short bgc);\r
+unsigned char CollisionTest(signed short *x1, signed short *y1, signed short *x2, signed short *y2, unsigned char Pattern, unsigned char RunHitTests, unsigned short *ObjNum, unsigned char TestCache, unsigned short TestFrame);\r
+void DrawLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2, unsigned char Method, unsigned char UseSprite);\r
+unsigned short CalcAngle(signed short x1, signed short y1, signed short x2, signed short y2);\r
+void AddHitTest(unsigned short ObjNum);\r
+void RemoveHitTest(unsigned short ObjNum);\r
+void HurtRadius(signed short x, signed short y, signed short StartDamage, signed short StopDamage, unsigned short StartDecRadius, unsigned short StopRadius, unsigned char Owner);\r
+void CollVel(signed short x, signed short y, float *xv, float *yv, unsigned char Attributes);\r
+void MessageBox(unsigned char *Buffer);\r
+void FillBuffer(void);\r
+unsigned char PlaySound(unsigned short Sound, unsigned char Repeat, unsigned short StartSound, unsigned short EndSound, unsigned long Pitch, float Volume);\r
+unsigned long MakeColor(unsigned char R, unsigned char G, unsigned char B);\r
+unsigned char MonoColor(unsigned long c);\r
+void __inline GetNextLineCoord(signed short *x, signed short *y, signed short *d, unsigned short dx, unsigned short dy, signed short xi, signed short yi);\r
+unsigned short GetObjectList(void);\r
+\r
+Pixel *Pixels[MAX_PIXELS];\r
+Cache **Caches;\r
+Sprite *Sprites[MAX_SPRITES];\r
+Object *Objects[MAX_OBJECTS];\r
+Player *Players[MAX_PLAYERS];\r
+PWeapon *PWeapons[MAX_PLAYERS][NUM_WEAPONS];\r
+ObjectList *ObjectLists[MAX_OBJLISTS];\r
+Sound Sounds[MAX_SOUNDS];\r
+SoundCache **SoundCaches;\r
+Class **Classes;\r
+Weapon **Weapons;\r
+unsigned char *Font;\r
+Line *Lines[MAX_LINES];\r
+Raster *Rasters[MAX_RASTERS];\r
+unsigned short HitTests[MAX_HITTESTS];\r
+unsigned char *Strings;\r
+Pal Palette[NUM_COLORS];\r
+unsigned char ColorInfo[NUM_COLORS];\r
+unsigned char *MenuItems[2][MAX_MENUITEMS];\r
+unsigned short MenuStack[16][3], MenuStackPos;\r
+KvidFile DataFile;\r
+float Gravity;\r
+SDL_Surface *VBuffer;\r
+unsigned char *DblBuffer;\r
+unsigned char FullScreen;\r
+signed short clip_x1, clip_x2;\r
+signed short clip_y1, clip_y2;\r
+unsigned short PagesFree;\r
+unsigned short BGSprite, BGFrame;\r
+unsigned char LevelFinished;\r
+unsigned short LevelWidth, LevelHeight;\r
+unsigned short MaxLW, MaxLH;\r
+unsigned char  *LevelBuffer[NUM_PLANES];\r
+unsigned short NumSprites;\r
+unsigned short NumClasses;\r
+unsigned short NumWeapons;\r
+unsigned short NumSounds;\r
+unsigned char DebugMode;\r
+unsigned short FrameRate;\r
+unsigned short FontSprite;\r
+signed short Regs[32];\r
+signed short GameVars[40];\r
+unsigned char StackPos;\r
+unsigned short Stack[MAX_STACK];\r
+unsigned char SpecialKey;\r
+unsigned short AsciiTable[256];\r
+unsigned char AsciiTable2[256];\r
+float Sine[360], Cosine[360];\r
+float WaveForms[5][360];\r
+double PreSine[360], PreCosine[360];\r
+volatile unsigned char KeyTable[256];\r
+unsigned char RepeatKey;\r
+double RepeatData;\r
+unsigned char *TextBuffer;\r
+unsigned char *KeyboardBuffer;\r
+unsigned char *LevelFileName, *ModFileName;\r
+unsigned char LevelType;\r
+unsigned short DispLevelWidth, DispLevelHeight;\r
+unsigned short KeybWritePos, KeybReadPos;\r
+unsigned char *SoundBuffer;\r
+signed short *TestBuffer;\r
+unsigned char UseSound;\r
+unsigned char FreeSound;\r
+unsigned short DSPAddress;\r
+unsigned char DMAChannel;\r
+unsigned char IRQLine;\r
+unsigned char OldMask;\r
+unsigned char DMAPage, DMAAddress, DMACount;\r
+unsigned char PICAddress;\r
+unsigned char ReadyBuffer, BufferReady;\r
+unsigned char Bit16, Stereo;\r
+unsigned short SBSampleRate;\r
+unsigned char NumPlays;\r
+unsigned short *FontBuffer;\r
+unsigned char ModeInfo[256];\r
+unsigned char *MenuBuffer;\r
+unsigned char FogSprite;\r
+signed short FogX, FogY;\r
+void (*TransOps[5])(unsigned long *Bg, unsigned long Amount);\r
+ModSample Samples[MAX_SAMPLES];\r
+ModChannel Channels[MAX_CHANNELS];\r
+ModEvent *Patterns;\r
+unsigned char PatternOrder[MAX_PATTERNS];\r
+unsigned char ModPlaying, ModLen, ModRepeat, ModChannels;\r
+unsigned char ModPattern, ModRow;\r
+unsigned short ModOffset;\r
+unsigned char ModBPM, ModTPD;\r
+unsigned char MenuActive;\r
+unsigned short NumMenuItems, CurMenuItem, StartMenuItem, MenuID;\r
+unsigned char GameType;\r
+unsigned char BPP;\r
+unsigned char Paused;\r
+unsigned short CurNew, CurComp;\r
+\r
+#include "sdlmap.h"\r
+#include "newdb.h"\r
+#include "dblbuf.h"\r
+#include "executor.h"\r
+#include "sb.h"\r
+\r
+/*\r
+void NewKeyInt()\r
+{\r
+    unsigned char Data;\r
+\r
+    raw_key = inp(0x60);\r
+    Data = inp(0x61) | 0x82;\r
+    outp(0x61, Data);\r
+    outp(0x61, Data & 0x7F);\r
+    outp(0x20, 0x20);\r
+    if(raw_key < 128)\r
+    {\r
+        if(SpecialKey == 1)\r
+        {\r
+            KeyTable[raw_key + 128] = 1;\r
+            SpecialKey = 0;\r
+            RepeatKey = raw_key + 128;\r
+            RepeatData = 250;\r
+            KeyboardBuffer[KeybWritePos++] = raw_key + 128;\r
+            if(KeybWritePos >= 500)\r
+                KeybWritePos = 0;\r
+        } else {\r
+            KeyTable[raw_key] = 1;\r
+            RepeatKey = raw_key;\r
+            RepeatData = 250;\r
+            KeyboardBuffer[KeybWritePos++] = raw_key;\r
+            if(KeybWritePos >= 500)\r
+                KeybWritePos = 0;\r
+        }\r
+    } else {\r
+        if(raw_key == 0xE0)\r
+        {\r
+            SpecialKey = 1;\r
+        } else {\r
+            RepeatKey = 0;\r
+            if(SpecialKey == 1)\r
+            {\r
+                KeyTable[raw_key] = 0;\r
+                SpecialKey = 0;\r
+            } else {\r
+                KeyTable[raw_key - 128] = 0;\r
+            }\r
+        }\r
+    }\r
+}\r
+*/\r
+\r
+double ntime(void)\r
+{\r
+    struct timeval tv;\r
+    \r
+    gettimeofday(&tv, NULL);\r
+    return((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));\r
+}\r
+\r
+unsigned char ReadKey(void)\r
+{\r
+    unsigned char Data;\r
+\r
+    if((Data = KeyboardBuffer[KeybReadPos]) != 0)\r
+    {\r
+        KeyboardBuffer[KeybReadPos] = 0;\r
+        if(++KeybReadPos >= 500)\r
+            KeybReadPos = 0;\r
+    }\r
+    return(Data);\r
+}\r
+\r
+void EmptyKeyBuffer(void)\r
+{\r
+    KeybWritePos = KeybReadPos = 0;\r
+    memset(KeyboardBuffer, 0, 500);\r
+}\r
+\r
+void CopyToMap(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char ColorPattern, unsigned char DestroyAll, unsigned short Attributes)\r
+{\r
+    unsigned short cx, cy, i;\r
+    unsigned long data;\r
+    unsigned char c;\r
+    unsigned char Colors[NUM_COLORS];\r
+    unsigned char NumColors;\r
+\r
+    NumColors = 0;\r
+    for(i = 0; i < NUM_COLORS; i++)\r
+    {\r
+        if(ColorInfo[i] == ColorPattern)\r
+            Colors[NumColors++] = i;\r
+    }\r
+    for(cy = 0; cy < h; cy++)\r
+    {\r
+        for(cx = 0; cx < w; cx++)\r
+        {\r
+            data = *(unsigned long *)Buffer;\r
+            Buffer += 4;\r
+            if(data != bgc)\r
+            {\r
+                if(((GetMapPixel(x + cx, y + cy, 1) & MAP_DESTROYABLE) == MAP_DESTROYABLE) || (DestroyAll == 1))\r
+                {\r
+                    if(Attributes != 0xFFFF)\r
+                        SetMapPixel(x + cx, y + cy, Attributes, 1);\r
+                    if(ColorPattern == 0)\r
+                        SetMapPixel(x + cx, y + cy, data, 0);\r
+                    else\r
+                    {\r
+                        c = Colors[rand() % NumColors];\r
+                        SetMapPixel(x + cx, y + cy, MakeColor(Palette[c].r, Palette[c].g, Palette[c].b), 0);\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void ReInit(void)\r
+{\r
+    unsigned short i, o;\r
+\r
+    for(i = 0; i < MAX_PIXELS; i++)\r
+        Pixels[i]->Used = 0;\r
+    for(i = 0; i < MAX_OBJECTS; i++)\r
+        Objects[i]->Used = 0;\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        for(o = 0; o < NUM_KEYS; o++)\r
+        {\r
+            Players[i]->Keys[o] = 0;\r
+            Players[i]->HeldKeys[o] = 0;\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_SPRITES; i++)\r
+        Sprites[i]->Used = 0;\r
+    for(i = 0; i < MAX_LINES; i++)\r
+        Lines[i]->Used = 0;\r
+    for(i = 0; i < MAX_RASTERS; i++)\r
+        Rasters[i]->Used = 0;\r
+    for(i = 0; i < MAX_SOUNDS; i++)\r
+        Sounds[i].Playing = 0;\r
+    for(i = 0; i < MAX_HITTESTS; i++)\r
+        HitTests[i] = 0xFFFF;\r
+    ModPlaying = 0;\r
+}\r
+\r
+/*\r
+void TimerInt(void)\r
+{\r
+    Ticks++;\r
+    TickError += FrameRate;\r
+    if(TickError >= TIMER_RES)\r
+    {\r
+        ReadyToGo = 1;\r
+        TickError -= TIMER_RES;\r
+    }\r
+    if(RepeatKey != 0)\r
+    {\r
+        if(--RepeatData == 0)\r
+        {\r
+            KeyboardBuffer[KeybWritePos++] = RepeatKey;\r
+            if(KeybWritePos >= 500)\r
+                KeybWritePos = 0;\r
+            RepeatData = 25;\r
+        }\r
+    }\r
+}\r
+*/\r
+\r
+void SetMapPixel(unsigned short x, unsigned short y, unsigned long c, unsigned short Handle)\r
+{\r
+    if((x >= LevelWidth) || (y >= LevelHeight))\r
+        return;\r
+    if(Handle == 0)\r
+        *(unsigned long *)&LevelBuffer[Handle][(x + (y * LevelWidth)) << 2] = c;\r
+    else\r
+        *(unsigned char *)&LevelBuffer[Handle][x + (y * LevelWidth)] = (unsigned short)c;\r
+}\r
+\r
+unsigned long GetMapPixel(unsigned short x, unsigned short y, unsigned short Handle)\r
+{\r
+    if((x >= LevelWidth) || (y >= LevelHeight))\r
+        return(0);\r
+    if(Handle == 0)\r
+        return(*(unsigned long *)&LevelBuffer[Handle][(x + (y * LevelWidth)) << 2]);\r
+    else\r
+        return((unsigned long)*(unsigned char *)&LevelBuffer[Handle][x + (y * LevelWidth)]);\r
+}\r
+\r
+void ShowMap(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned short MapX, unsigned short MapY)\r
+{\r
+    unsigned short Window;\r
+    unsigned short cwx, cwy;\r
+    signed short x, y;\r
+    unsigned short i;\r
+    unsigned short CurFrame;\r
+    unsigned char Template;\r
+\r
+    if((MapX >= LevelWidth) || (MapY >= LevelHeight))\r
+        return;\r
+    DBSetClip(x1, y1, x2, y2);\r
+    cwx = (MapX / 2) % Caches[BGSprite]->w;\r
+    cwy = (MapY / 2) % Caches[BGSprite]->h;\r
+    #if CP_BLUR == 0\r
+    for(y = (signed short)(y1 - Caches[BGSprite]->h); y < (signed short)(y2 + Caches[BGSprite]->h); y += Caches[BGSprite]->h)\r
+    {\r
+        for(x = (signed short)(x1 - Caches[BGSprite]->w); x < (signed short)(x2 + Caches[BGSprite]->w); x += Caches[BGSprite]->w)\r
+        {\r
+            DBCopyBufferClip((signed short)x - cwx, (signed short)y - cwy, Caches[BGSprite]->Frames[BGFrame], Caches[BGSprite]->w, Caches[BGSprite]->h, -1);\r
+        }\r
+    }\r
+    #endif\r
+    DBCopyBufferClip((signed short)x1 - (signed short)MapX, (signed short)y1 - (signed short)MapY, LevelBuffer[0], LevelWidth, LevelHeight, 0);\r
+    //DBCopyMapBufferClip((signed short)x1 - (signed short)MapX, (signed short)y1 - (signed short)MapY, LevelBuffer[0], LevelBuffer[1], LevelWidth, LevelHeight);\r
+    for(i = 0; i < MAX_LINES; i++)\r
+    {\r
+        if(Lines[i]->Used > 0)\r
+        {\r
+            if(Lines[i]->UseSprite != 0xFF)\r
+            {\r
+                if(Lines[i]->Transparent != 0)\r
+                    DBSpriteLineTrans(Lines[i]->x1 - MapX + x1 - Caches[Lines[i]->UseSprite]->cx[Lines[i]->CurFrame], Lines[i]->y1 - MapY + y1 - Caches[Lines[i]->UseSprite]->cy[Lines[i]->CurFrame], Lines[i]->x2 - MapX + x1 - Caches[Lines[i]->UseSprite]->cx[Lines[i]->CurFrame], Lines[i]->y2 - MapY + y1 - Caches[Lines[i]->UseSprite]->cy[Lines[i]->CurFrame], Caches[Lines[i]->UseSprite]->Frames[Lines[i]->CurFrame], Caches[Lines[i]->UseSprite]->w, Caches[Lines[i]->UseSprite]->h, Lines[i]->Transparent - 1);\r
+                else\r
+                    DBSpriteLine(Lines[i]->x1 - MapX + x1 - Caches[Lines[i]->UseSprite]->cx[Lines[i]->CurFrame], Lines[i]->y1 - MapY + y1 - Caches[Lines[i]->UseSprite]->cy[Lines[i]->CurFrame], Lines[i]->x2 - MapY + x1 - Caches[Lines[i]->UseSprite]->cx[Lines[i]->CurFrame], Lines[i]->y2 - MapY + y1 - Caches[Lines[i]->UseSprite]->cy[Lines[i]->CurFrame], Caches[Lines[i]->UseSprite]->Frames[Lines[i]->CurFrame], Caches[Lines[i]->UseSprite]->w, Caches[Lines[i]->UseSprite]->h);\r
+            } else {\r
+                if(Lines[i]->Transparent != 0)\r
+                    DBLineTrans(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, Lines[i]->Transparent - 1);\r
+                else\r
+                    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);\r
+            }\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_PIXELS; i++)\r
+    {\r
+        if(Pixels[i]->Used == 1)\r
+            DBPSetC((unsigned short)(Pixels[i]->x - MapX + x1), (unsigned short)(Pixels[i]->y - MapY + y1), Pixels[i]->c);\r
+    }\r
+    for(i = 0; i < MAX_SPRITES; i++)\r
+    {\r
+        if(Sprites[i]->Used == 1)\r
+        {\r
+            CurFrame = Sprites[i]->CurFrame;\r
+            Template = Sprites[i]->Template;\r
+           CurFrame %= Caches[Template]->NumFrames;\r
+            if(Sprites[i]->Transparent != 0)\r
+                DBCopyBufferClipTrans((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, Sprites[i]->Transparent - 1);\r
+            else\r
+                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);\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_RASTERS; i++)\r
+    {\r
+        if(Rasters[i]->Used == 1)\r
+        {\r
+            if(Rasters[i]->Type == 0)\r
+            {\r
+                if(Rasters[i]->Transparent != 0)\r
+                    DBFPolyTrans(x1 - MapX + Rasters[i]->x1, y1 - MapY + Rasters[i]->y1, x1 - MapX + Rasters[i]->x2, y1 - MapY + Rasters[i]->y2, x1 - MapX + Rasters[i]->x3, y1 - MapY + Rasters[i]->y3, Rasters[i]->Color, Rasters[i]->Transparent - 1);\r
+                else\r
+                    DBFPoly(x1 - MapX + Rasters[i]->x1, y1 - MapY + Rasters[i]->y1, x1 - MapX + Rasters[i]->x2, y1 - MapY + Rasters[i]->y2, x1 - MapX + Rasters[i]->x3, y1 - MapY + Rasters[i]->y3, Rasters[i]->Color);\r
+            }\r
+            if(Rasters[i]->Type == 1)\r
+            {\r
+                if(Rasters[i]->Transparent != 0)\r
+                    DBFCircleTrans(x1 - MapX + Rasters[i]->x1, y1 - MapY + Rasters[i]->y1, Rasters[i]->x2, Rasters[i]->Color, 1, 1, Rasters[i]->Transparent - 1);\r
+                else\r
+                    DBFCircle(x1 - MapX + Rasters[i]->x1, y1 - MapY + Rasters[i]->y1, Rasters[i]->x2, Rasters[i]->Color, 1, 1);\r
+            }\r
+        }\r
+    }\r
+    /*for(y = (signed short)(y1 - Caches[FogSprite]->h); y < (signed short)(y2 + Caches[FogSprite]->h); y += Caches[FogSprite]->h)\r
+    {\r
+        for(x = (signed short)(x1 - Caches[FogSprite]->w); x < (signed short)(x2 + Caches[FogSprite]->w); x += Caches[FogSprite]->w)\r
+        {\r
+            DBCopyBufferClipTrans((signed short)x - FogX, (signed short)y - FogY, Caches[FogSprite]->Frames[0], Caches[FogSprite]->w, Caches[FogSprite]->h, -1, 1);\r
+        }\r
+    }*/\r
+    DBSetClip(0, 0, 319, 199);\r
+}\r
+\r
+unsigned char PlaySound(unsigned short Sound, unsigned char Repeat, unsigned short StartSound, unsigned short EndSound, unsigned long Pitch, float Volume)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = StartSound; i <= EndSound; i++)\r
+    {\r
+        if(Sounds[i].Playing == 0)\r
+        {\r
+            Sounds[i].Sound = Sound;\r
+            Sounds[i].Repeat = Repeat;\r
+            Sounds[i].Offset = 0;\r
+            Sounds[i].Pitch = Pitch;\r
+            Sounds[i].Volume = Volume;\r
+            Sounds[i].PitchError = 0;\r
+            Sounds[i].Playing = 1;\r
+            return(i);\r
+        }\r
+    }\r
+    return(0xFF);\r
+}\r
+\r
+void InitCodeTable(void)\r
+{\r
+    unsigned short i;\r
+\r
+    CurComp = 1;\r
+    CurNew = 0;\r
+    for(i = 0; i < 4096; i++)\r
+    {\r
+        Codes[i].Parent = -1;\r
+        Codes[i].Size = -1;\r
+        Codes[i].Value = -1;\r
+    }\r
+}\r
+\r
+signed short FindCode(signed long Value, signed short Parent)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = 0; i < (1 << CurComp); i++)\r
+    {\r
+        if((Codes[i].Value == Value) && (Codes[i].Parent == Parent))\r
+            return(i);\r
+    }\r
+    return(-1);\r
+}\r
+\r
+unsigned long ReadVarLen(KvidFile *FileStr)\r
+{\r
+    unsigned long Value;\r
+    unsigned char Finished, Shift;\r
+\r
+    Value = 0;\r
+    Finished = Shift = 0;\r
+    while(Finished == 0)\r
+    {\r
+        if(FileReadBits(1, FileStr) == 1)\r
+            Finished = 1;\r
+        Value += FileReadBits(7, FileStr) << Shift;\r
+        Shift += 7;\r
+    }\r
+    return(Value);\r
+}\r
+\r
+unsigned char AddCode(signed long Value, signed short Parent)\r
+{\r
+    Codes[CurNew].Value = Value;\r
+    Codes[CurNew].Parent = Parent;\r
+    if(Parent == -1)\r
+        Codes[CurNew].Size = 0;\r
+    else\r
+        Codes[CurNew].Size = Codes[Parent].Size + 1;\r
+    if(++CurNew == (1 << CurComp))\r
+    {\r
+        if(++CurComp >= 13)\r
+        {\r
+            InitCodeTable();\r
+            return(1);\r
+        }\r
+    }\r
+    return(0);\r
+}\r
+\r
+unsigned char LoadNewLevel(KvidFile *LevelFile)\r
+{\r
+    unsigned short i, p, x, y;\r
+    unsigned short CC, CurCode;\r
+    signed short Parent, CodeNum, Length, RLECount;\r
+    signed long Col, LastCol;\r
+    unsigned char InRLE, InCode, SType, NoAdd, HasParent, ReInited;\r
+\r
+    ReInit();\r
+    FileRead((void *)&LevelWidth, 2, LevelFile);\r
+    FileRead((void *)&LevelHeight, 2, LevelFile);\r
+    DispLevelWidth = LevelWidth;\r
+    DispLevelHeight = LevelHeight;\r
+    for(p = 0; p < 2; p++)\r
+    {\r
+        InitCodeTable();\r
+        Col = -1;\r
+        InRLE = InCode = 0;\r
+        NoAdd = 1;\r
+        HasParent = 0;\r
+        for(y = 0; y < LevelHeight; y++)\r
+        {\r
+            for(x = 0; x < LevelWidth; x++)\r
+            {\r
+                LastCol = Col;\r
+                if((InRLE == 0) && (InCode == 0))\r
+                {\r
+                    InRLE = FileReadBits(1, LevelFile);\r
+                    SType = FileReadBits(2, LevelFile);\r
+                    if(InRLE == 1)\r
+                        RLECount = ReadVarLen(LevelFile);\r
+                    if(SType == 2)\r
+                    {\r
+                        InCode = 1;\r
+                        CurCode = FileReadBits(CurComp, LevelFile);\r
+                        Length = Codes[CurCode].Size;\r
+                        CC = CurCode;\r
+                        for(i = 0; i < Length; i++)\r
+                            CC = Codes[CC].Parent;\r
+                        Col = Codes[CC].Value;\r
+                    }\r
+                    if(SType == 0)\r
+                        Col = FileReadBits(16, LevelFile);\r
+                    if(NoAdd == 0)\r
+                    {\r
+                        if(HasParent == 0)\r
+                        {\r
+                            if((CodeNum = FindCode(LastCol, -1)) == -1)\r
+                            {\r
+                                Parent = CurNew;\r
+                                ReInited = AddCode(LastCol, -1);\r
+                            } else {\r
+                                Parent = CodeNum;\r
+                                ReInited = (FindCode(Col, CodeNum) == -1)?0:1;\r
+                            }\r
+                        } else {\r
+                            ReInited = 0;\r
+                        }\r
+                        HasParent = 0;\r
+                        if(ReInited == 0)\r
+                            AddCode(Col, Parent);\r
+                    }\r
+                    if(FindCode(Col, -1) == -1)\r
+                        AddCode(Col, -1);\r
+                    NoAdd = 0;\r
+                }\r
+                if(InCode == 1)\r
+                {\r
+                    CC = CurCode;\r
+                    for(i = 0; i < Length; i++)\r
+                        CC = Codes[CC].Parent;\r
+                    Col = Codes[CC].Value;\r
+                    if(--Length < 0)\r
+                    {\r
+                        if(InRLE == 1)\r
+                        {\r
+                            if(--RLECount <= 0)\r
+                                InRLE = InCode = 0;\r
+                            else\r
+                                Length = Codes[CurCode].Size;\r
+                        } else {\r
+                            InCode = 0;\r
+                        }\r
+                        if(InCode == 0)\r
+                        {\r
+                            HasParent = 1;\r
+                            Parent = CurCode;\r
+                        }\r
+                    }\r
+                } else {\r
+                    if(InRLE == 1)\r
+                    {\r
+                        if(--RLECount <= 0)\r
+                            InRLE = 0;\r
+                    }\r
+                }\r
+                if(p == 0)\r
+                    SetMapPixel(x, y, Color16To32((unsigned short)Col), p);\r
+                else\r
+                    SetMapPixel(x, y, Col, p);\r
+            }\r
+        }\r
+    }\r
+    SpawnObject(0, -1, 0, 0, 0, 0);\r
+    FileClose(LevelFile);\r
+    return(0);\r
+}\r
+\r
+unsigned char LoadBMPLevel(KvidFile *LevelFile)\r
+{\r
+    unsigned short x, y;\r
+    unsigned long Buffer;\r
+    Color Col;\r
+\r
+    ReInit();\r
+    FileSkip(LevelFile, 16);\r
+    FileRead((void *)&Buffer, 4, LevelFile);\r
+    LevelWidth = DispLevelWidth = (unsigned short)Buffer;\r
+    FileRead((void *)&Buffer, 4, LevelFile);\r
+    LevelHeight = DispLevelHeight = (unsigned short)Buffer;\r
+    FileSkip(LevelFile, 28);\r
+    for(y = LevelHeight; y > 0; y--)\r
+    {\r
+        for(x = 0; x < LevelWidth; x++)\r
+        {\r
+            FileRead((void *)&Col, 3, LevelFile);\r
+            Col.Reserved = 0;\r
+            SetMapPixel(x, y - 1, *(unsigned long *)&Col, 0);\r
+            if((Col.R == 0) && (Col.G == 0) && (Col.B == 0))\r
+            {\r
+                SetMapPixel(x, y - 1, MAP_WALKABLE | MAP_SHOOTABLE, 1);\r
+            } else {\r
+                if((Col.R == Col.G) && (Col.R == Col.B))\r
+                    SetMapPixel(x, y - 1, 0, 1);\r
+                else\r
+                    SetMapPixel(x, y - 1, MAP_DESTROYABLE, 1);\r
+            }\r
+        }\r
+        FileSkip(LevelFile, LevelWidth % 4);\r
+    }\r
+    FileClose(LevelFile);\r
+    SpawnObject(0, -1, 0, 0, 0, 0);\r
+    return(0);\r
+}\r
+\r
+unsigned char LoadLevel(unsigned char *Name)\r
+{\r
+    KvidFile LevelFile, PalFile;\r
+    unsigned long Offset, Size;\r
+    unsigned short x, y, Count, Count2, Signature, i, o;\r
+    unsigned char Handle, RLEBase, c;\r
+    signed short ox, oy;\r
+    signed char Change, PalChange;\r
+    Color Col;\r
+\r
+    DBFRect(0, 0, 319, 199, MakeColor(0, 0, 0));\r
+    if(OpenFile(Name, &LevelFile) == 0)\r
+        return(1);\r
+    FileRead((void *)&Signature, 2, &LevelFile);\r
+    if(Signature == 0x4C4E)\r
+        return(LoadNewLevel(&LevelFile));\r
+    if(Signature == 0x4D42)\r
+        return(LoadBMPLevel(&LevelFile));\r
+    if(Signature != 0x464B)\r
+        return(2);\r
+    ReInit();\r
+    FileRead((void *)&LevelWidth, 2, &LevelFile);\r
+    PalChange = 0;\r
+    if(LevelWidth == 0)\r
+    {\r
+        FileRead((void *)&c, 1, &LevelFile);\r
+        FileRead((void *)TextBuffer, c, &LevelFile);\r
+        TextBuffer[c] = 0;\r
+        FileRead((void *)&LevelWidth, 2, &LevelFile);\r
+        if(OpenFile(TextBuffer, &PalFile) != 0)\r
+        {\r
+            PalChange = 1;\r
+            FileRead((void *)Palette, sizeof(Pal) * 256, &PalFile);\r
+            FileClose(&PalFile);\r
+        }\r
+    }\r
+    FileRead((void *)&LevelHeight, 2, &LevelFile);\r
+    DispLevelWidth = LevelWidth;\r
+    DispLevelHeight = LevelHeight;\r
+    FileRead((void *)&RLEBase, 1, &LevelFile);\r
+    Size = LevelWidth * LevelHeight;\r
+    for(Handle = 0; Handle < 2; Handle++)\r
+    {\r
+        x = 0;\r
+        y = 0;\r
+        Count = 0;\r
+        for(Offset = 0; Offset < Size; Offset++)\r
+        {\r
+            if(Count > 0)\r
+                Count--;\r
+            if(Count == 0)\r
+            {\r
+                c = FileGetChar(&LevelFile);\r
+                if(c >= RLEBase)\r
+                {\r
+                    Count = (c - RLEBase) + 1;\r
+                    c = FileGetChar(&LevelFile);\r
+                }\r
+            }\r
+            if((Offset & 0xFFFF) == 0)\r
+            {\r
+                sprintf(TextBuffer, "Loading %s... %u%%\0", Name, (unsigned short)(50 * ((double)Offset / (double)Size)) + (Handle * 50));\r
+                DBPrint(TextBuffer, 0, 0, 255);\r
+                DisplayDB();\r
+            }\r
+            if(Handle == 0)\r
+                SetMapPixel(x, y, MakeColor(Palette[c].r, Palette[c].g, Palette[c].b), Handle);\r
+            else\r
+                SetMapPixel(x, y, (unsigned long)c, Handle);\r
+            if(++x >= LevelWidth)\r
+            {\r
+                x = 0;\r
+                y++;\r
+            }\r
+        }\r
+    }\r
+    if(PalChange == 1)\r
+    {\r
+        if(OpenFile("DefaultPalette", &PalFile) != 0)\r
+        {\r
+            FileRead((void *)Palette, sizeof(Pal) * 256, &PalFile);\r
+            FileClose(&PalFile);\r
+        }\r
+    }\r
+    FileRead((void *)&Count, 2, &LevelFile);\r
+    GameType = 255;\r
+    for(i = 0; i < Count; i++)\r
+    {\r
+        FileRead((void *)&Signature, 2, &LevelFile);\r
+        FileRead((void *)&x, 2, &LevelFile);\r
+        FileRead((void *)&y, 2, &LevelFile);\r
+        FileRead((void *)&Count2, 2, &LevelFile);\r
+        for(o = 0; o < Count2; o++)\r
+        {\r
+            Regs[FileGetChar(&LevelFile) + (FileGetChar(&LevelFile) << 8)] = FileGetChar(&LevelFile) + (FileGetChar(&LevelFile) << 8);\r
+        }\r
+        SpawnObject(Signature, -1, x, y, 0, 0);\r
+    }\r
+    FileClose(&LevelFile);\r
+    if(GameType == 255)\r
+        SpawnObject(0, -1, 0, 0, 0, 0);\r
+    /*for(Offset = 0; Offset < 300; Offset++)\r
+    {\r
+        x = (unsigned short)(rand() % LevelWidth);\r
+        y = (unsigned short)(rand() % LevelWidth);\r
+        while(GetMapPixel(x, y, 0) != MakeColor(Palette[6].r, Palette[6].g, Palette[6].b))\r
+        {\r
+            x = (unsigned short)(rand() % LevelWidth);\r
+            y = (unsigned short)(rand() % LevelWidth);\r
+        }\r
+        for(oy = -1; oy <= 1; oy++)\r
+        {\r
+            for(ox = -1; ox <= 1; ox++)\r
+            {\r
+                Signature = GetMapPixel(x, y, 0);\r
+                Col = *(Color *)&Signature;\r
+                if((ox == 0) && (oy == 0))\r
+                    Change = 3;\r
+                if((ox != 0) && (oy == 0) || (ox == 0) && (oy != 0))\r
+                    Change = 2;\r
+                if((ox != 0) && (oy != 0))\r
+                    Change = 1;\r
+                SetMapPixel((signed short)x + ox, (signed short)y + oy, MakeColor(Col.r - Change, Col.g - (Change << 1), Col.b - Change), 0);\r
+                sprintf(TextBuffer, "Loading %s... %u%%\0", Name, (unsigned short)(100 * ((double)Offset / (double)300)));\r
+                DBPrint(TextBuffer, 0, 0, 255);\r
+                DisplayDB();\r
+            }\r
+        }\r
+    }*/\r
+    return(0);\r
+}\r
+\r
+void RandomLevel(void)\r
+{\r
+    unsigned short x, y, i, o;\r
+    unsigned char c0, c1, c2, c3, c4;\r
+\r
+    for(y = 0; y < LevelHeight; y++)\r
+    {\r
+        for(x = 0; x < LevelWidth; x++)\r
+        {\r
+            //SetMapPixel(x, y, (unsigned char)((rand() % 4) + 20), 0);\r
+            SetMapPixel(x, y, 0, 0);\r
+        }\r
+    }\r
+    for(y = 0; y < LevelHeight; y++)\r
+    {\r
+        for(x = 0; x < LevelWidth; x++)\r
+        {\r
+            SetMapPixel(x, y, MAP_WALKABLE | MAP_SHOOTABLE | MAP_DESTROYABLE, 1);\r
+        }\r
+    }\r
+    for(i = 0; i < 75; i++)\r
+    {\r
+        x = rand() % LevelWidth;\r
+        y = rand() % LevelHeight;\r
+        CopyToMap(x - 15, y - 11, Caches[11]->Frames[rand() % Caches[11]->NumFrames], Caches[11]->w, Caches[11]->h, 0, 0, 0, 0);\r
+    }\r
+    for(i = 0; i < 150; i++)\r
+    {\r
+        x = rand() % LevelWidth;\r
+        y = rand() % LevelHeight;\r
+        CopyToMap(x - Caches[0]->cx[0], y - Caches[0]->cy[0], Caches[0]->Frames[0], Caches[0]->w, Caches[0]->h, 0, 3, 0, MAP_DESTROYABLE);\r
+    }\r
+    /*for(y = 0; y < LevelHeight; y++)\r
+    {\r
+        for(x = 0; x < LevelWidth; x++)\r
+        {\r
+            c0 = GetMapPixel(x, y, 0);\r
+            if(c0 > 0)\r
+            {\r
+                c1 = GetMapPixel(x - 1, y, 0);\r
+                c2 = GetMapPixel(x + 1, y, 0);\r
+                c3 = GetMapPixel(x, y - 1, 0);\r
+                c4 = GetMapPixel(x, y + 1, 0);\r
+                c1 = (c1 == 0)?c0:c1;\r
+                c2 = (c2 == 0)?c0:c2;\r
+                c3 = (c3 == 0)?c0:c3;\r
+                c4 = (c4 == 0)?c0:c4;\r
+                SetMapPixel(x, y, (unsigned char)((c1 + c2 + c3 + c4) >> 2), 0);\r
+            }\r
+        }\r
+    }*/\r
+    for(i = 0; i < 100; i++)\r
+    {\r
+        x = rand() % LevelWidth;\r
+        y = rand() % LevelHeight;\r
+        while((GetMapPixel(x, y, 1) & MAP_WALKABLE) == 0)\r
+        {\r
+            x = rand() % LevelWidth;\r
+            y = rand() % LevelHeight;\r
+        }\r
+        while((GetMapPixel(x, y, 1) & MAP_WALKABLE) == MAP_WALKABLE)\r
+            y++;\r
+        c0 = rand() % Caches[12]->NumFrames;\r
+        CopyToMap(x - Caches[12]->cx[c0], y - Caches[12]->cy[c0], Caches[12]->Frames[c0], Caches[12]->w, Caches[12]->h, 0, 0, 0, MAP_WALKABLE | MAP_TEMPORARY);\r
+    }\r
+    for(i = 0; i < 4; i++)\r
+    {\r
+        for(o = 0; o < 15; o++)\r
+        {\r
+            x = rand() % LevelWidth;\r
+            y = rand() % LevelHeight;\r
+            while((GetMapPixel(x, y, 1) & MAP_WALKABLE) == 0)\r
+            {\r
+                x = rand() % (LevelWidth / 10);\r
+                y = rand() % (LevelHeight / 10);\r
+            }\r
+            if(i == 0)\r
+                while((GetMapPixel(x, ++y, 1) & MAP_WALKABLE) == MAP_WALKABLE);\r
+            if(i == 1)\r
+                while((GetMapPixel(--x, y, 1) & MAP_WALKABLE) == MAP_WALKABLE);\r
+            if(i == 2)\r
+                while((GetMapPixel(x, --y, 1) & MAP_WALKABLE) == MAP_WALKABLE);\r
+            if(i == 3)\r
+                while((GetMapPixel(++x, y, 1) & MAP_WALKABLE) == MAP_WALKABLE);\r
+            c0 = rand() % Caches[12]->NumFrames;\r
+            Regs[0] = i;\r
+            SpawnObject(93, -1, x, y, 0, 0);\r
+        }\r
+    }\r
+    for(y = 0; y < LevelHeight; y++)\r
+    {\r
+        for(x = 0; x < LevelWidth; x++)\r
+        {\r
+            if((GetMapPixel(x, y, 1) & MAP_TEMPORARY) == MAP_TEMPORARY)\r
+                SetMapPixel(x, y, MAP_DESTROYABLE, 1);\r
+        }\r
+    }\r
+    strcpy(LevelFileName, "Random");\r
+    DispLevelWidth = LevelWidth;\r
+    DispLevelHeight = LevelHeight;\r
+    SpawnObject(0, -1, 0, 0, 0, 0);\r
+}\r
+\r
+void DrawScreen(void)\r
+{\r
+    unsigned short i, o, cx, cy;\r
+    signed short tx, ty, CurWeapon, x, y, x2, y2;\r
+    float Per;\r
+\r
+    #if CP_BLUR == 0\r
+    DBFillScreen(0);\r
+    #else\r
+    DBFRectTrans(0, 0, 319, 199, MakeColor(16, 16, 16), 1);\r
+    #endif\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        if(Players[i]->Visual == 1)\r
+        {\r
+            x = Objects[Players[i]->VPObject]->x;\r
+            y = Objects[Players[i]->VPObject]->y;\r
+            cx = (Players[i]->VPointX2 - Players[i]->VPointX1) >> 1;\r
+            cy = (Players[i]->VPointY2 - Players[i]->VPointY1) >> 1;\r
+            if(x > LevelWidth - cx - 2) x = LevelWidth - cx - 2;\r
+            if(y > LevelHeight - cy - 2) y = LevelHeight - cy - 2;\r
+            if(x < cx) x = cx;\r
+            if(y < cy) y = cy;\r
+            ShowMap(Players[i]->VPointX1, Players[i]->VPointY1, Players[i]->VPointX2, Players[i]->VPointY2, x - cx, y - cy);\r
+            //*(unsigned long *)(Players[i]->Masks[0].Buffer + ((((unsigned short)Objects[Players[i]->Object]->y - (y - cy)) * (Players[i]->VPointX2 - Players[i]->VPointX1 + 1) + ((unsigned short)Objects[Players[i]->Object]->x - (x - cx))) << 2)) = MakeColor(255, 0, 0);\r
+            DBSetClip(Players[i]->VPointX1, Players[i]->VPointY1, Players[i]->VPointX2, Players[i]->VPointY2);\r
+            for(o = 0; o < NUM_MASKS; o++)\r
+            {\r
+                if(Players[i]->Masks[o].Method != 0)\r
+                    DBCopyBufferClipTrans(Players[i]->VPointX1, Players[i]->VPointY1, Players[i]->Masks[o].Buffer, Players[i]->VPointX2 - Players[i]->VPointX1 + 1, Players[i]->VPointY2 - Players[i]->VPointY1 + 1, -1, Players[i]->Masks[o].Method - 1);\r
+            }\r
+            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));\r
+            y2 = (unsigned short)((unsigned short)(Objects[Players[i]->Object]->y) - (Sine[(unsigned short)Players[i]->Angle] * 15) - y + cy + Players[i]->VPointY1 - 2);\r
+            DBPSetCTrans(x2 - 1, y2, Players[i]->CrossColor, 2);\r
+            DBPSetCTrans(x2 + 1, y2, Players[i]->CrossColor, 2);\r
+            DBPSetCTrans(x2, y2 - 1, Players[i]->CrossColor, 2);\r
+            DBPSetCTrans(x2, y2 + 1, Players[i]->CrossColor, 2);\r
+            if(Players[i]->Change)\r
+            {\r
+                tx = (signed short)(Objects[Players[i]->Object]->x - x + cx + Players[i]->VPointX1 - (Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->NameLength * 2));\r
+                ty = (signed short)(Objects[Players[i]->Object]->y - y + cy + Players[i]->VPointY1 - 20);\r
+                DBPrint((unsigned char *)&Strings[Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->Name], tx, ty, 0);\r
+            }\r
+            DBSetClip(0, 0, 319, 199);\r
+            CurWeapon = Players[i]->CurWeapon;\r
+            if(PWeapons[i][CurWeapon]->ReloadTimer == 0)\r
+                Per = (float)PWeapons[i][CurWeapon]->AmmoLeft / (float)Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->Ammo;\r
+            else\r
+                Per = (float)PWeapons[i][CurWeapon]->ReloadTimer / (float)Weapons[PWeapons[i][CurWeapon]->Weapon]->ReloadDelay;\r
+            if(Per > 0)\r
+                DBFRect(Players[i]->AMeterX1, Players[i]->AMeterY1, Players[i]->AMeterX1 + (signed short)(Per * (Players[i]->AMeterX2 - Players[i]->AMeterX1)), Players[i]->AMeterY2, MakeColor(255 - (Per * 255), 0, 255));\r
+            Per = (float)Players[i]->Health / (float)Players[i]->MaxHealth;\r
+            if(Per > 0)\r
+            {\r
+                if(Per >= 0.5)\r
+                    DBFRect(Players[i]->LMeterX1, Players[i]->LMeterY1, Players[i]->LMeterX1 + (signed short)(Per * (Players[i]->LMeterX2 - Players[i]->LMeterX1)), Players[i]->LMeterY2, MakeColor(255 - ((Per - 0.5) * 254), 255, 0));\r
+                else\r
+                    DBFRect(Players[i]->LMeterX1, Players[i]->LMeterY1, Players[i]->LMeterX1 + (signed short)(Per * (Players[i]->LMeterX2 - Players[i]->LMeterX1)), Players[i]->LMeterY2, MakeColor(255, 510 * Per, 0));\r
+            }\r
+            sprintf(TextBuffer, "Lives: %i\0", Players[i]->Lives);\r
+            DBPrint(TextBuffer, Players[i]->lx, Players[i]->ly, 255);\r
+            sprintf(TextBuffer, "Kills: %i\0", Players[i]->Kills);\r
+            DBPrint(TextBuffer, Players[i]->kx, Players[i]->ky, 255);\r
+            if(Weapons[PWeapons[i][CurWeapon]->Weapon]->MaxClips > 0)\r
+            {\r
+                sprintf(TextBuffer, "Ammo: %i\0", PWeapons[i][CurWeapon]->NumClips);\r
+                DBPrint(TextBuffer, Players[i]->cx, Players[i]->cy, 255);\r
+            }\r
+        }\r
+    }\r
+    DBPrint(TextBuffer, 319 - (sprintf(TextBuffer, "%s (%u x %u)", LevelFileName, DispLevelWidth, DispLevelHeight) * 4), 194, 255);\r
+    sprintf(TextBuffer, "%l08X", GetMapPixel(Objects[Players[1]->Object]->x, Objects[Players[1]->Object]->y, KeyTable[2]));\r
+    DBPrint(TextBuffer, 0, 194, 255);\r
+    #if SHOW_MAP == 1\r
+        for(y = 0; y < 40; y++)\r
+        {\r
+            for(x = 0; x < 64; x++)\r
+            {\r
+                DBPSetCTrans(128 + x, 160 + y, GetMapPixel((float)x * ((float)LevelWidth / 64), (float)y * ((float)LevelHeight / 40), 0), 2);\r
+            }\r
+        }\r
+        for(i = 0; i < MAX_PLAYERS; i++)\r
+        {\r
+            if(Players[i]->Used == 1)\r
+            {\r
+               DBPSetC(128 + (unsigned short)((float)Objects[Players[i]->Object]->x / ((float)LevelWidth / 64)), 160 + (unsigned short)((float)Objects[Players[i]->Object]->y / ((float)LevelHeight / 40)), MakeColor(200, 100, 0));\r
+            }\r
+        }\r
+    #else\r
+        DBCopyBufferClip(143, 180, Caches[15]->Frames[0], Caches[15]->w, Caches[15]->h, 0);\r
+    #endif\r
+}\r
+\r
+unsigned short CalcAngle(signed short x1, signed short y1, signed short x2, signed short y2)\r
+{\r
+    double a;\r
+    unsigned char Q;\r
+\r
+    if(x1 == x2)\r
+    {\r
+        if(y1 >= y2)\r
+          return(90);\r
+        if(y1 < y2)\r
+          return(270);\r
+    }\r
+    a = atan((double)(y1 - y2) / (double)(x1 - x2));\r
+    if(a < 0)\r
+        a = -a;\r
+    if((y1 >= y2) && (x1 < x2))\r
+        Q = 0;\r
+    if((y1 >= y2) && (x1 >= x2))\r
+    {\r
+        Q = 1;\r
+        a = 1.570796 - a;\r
+    }\r
+    if((y1 < y2) && (x1 >= x2))\r
+        Q = 2;\r
+    if((y1 < y2) && (x1 < x2))\r
+    {\r
+        Q = 3;\r
+        a = 1.570796 - a;\r
+    }\r
+    return((unsigned short)(((a + (Q * 1.570796)) / 3.141593) * 180));\r
+}\r
+\r
+unsigned long MakeColor(unsigned char R, unsigned char G, unsigned char B)\r
+{\r
+    return(((unsigned short)R << 16) + ((unsigned short)G << 8) + (unsigned short)B);\r
+}\r
+\r
+unsigned char GetEvents(void)\r
+{\r
+    unsigned short i;\r
+    SDL_Event e;\r
+    \r
+    while(SDL_PollEvent(&e))\r
+    {\r
+       if(e.type == SDL_QUIT)\r
+           return(1);\r
+       if(e.type == SDL_KEYDOWN)\r
+       {\r
+           for(i = 0; sdlmap[i].sdl != -1; i++)\r
+           {\r
+               if(sdlmap[i].sdl == e.key.keysym.sym)\r
+                   break;\r
+           }\r
+           if(sdlmap[i].sdl != -1)\r
+           {\r
+               KeyTable[sdlmap[i].dos] = 1;\r
+               RepeatKey = sdlmap[i].dos;\r
+               RepeatData = ntime() + 0.25;\r
+               KeyboardBuffer[KeybWritePos++] = sdlmap[i].dos;\r
+               if(KeybWritePos >= 500)\r
+                   KeybWritePos = 0;\r
+           }\r
+       }\r
+       if(e.type == SDL_KEYUP)\r
+       {\r
+           for(i = 0; sdlmap[i].sdl != -1; i++)\r
+           {\r
+               if(sdlmap[i].sdl == e.key.keysym.sym)\r
+                   break;\r
+           }\r
+           if(sdlmap[i].sdl != -1)\r
+           {\r
+               KeyTable[sdlmap[i].dos] = 0;\r
+               RepeatKey = 0;\r
+           }\r
+       }\r
+    }\r
+    if((RepeatKey != 0) && (ntime() > RepeatData))\r
+    {\r
+       KeyboardBuffer[KeybWritePos++] = RepeatKey;\r
+       if(KeybWritePos >= 500)\r
+           KeybWritePos = 0;\r
+       RepeatData = ntime() + 0.025;\r
+    }\r
+    return(0);\r
+}\r
+\r
+void GetInputs(void)\r
+{\r
+    unsigned char i, o, u;\r
+\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        for(o = 0; o < NUM_KEYS; o++)\r
+        {\r
+            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)))\r
+            {\r
+                if((Players[i]->Keys[o] == 0) && (Players[i]->HeldKeys[o] == 0))\r
+                {\r
+                    Players[i]->Keys[o] = 1;\r
+                } else {\r
+                    Players[i]->Keys[o] = 2;\r
+                }\r
+            } else {\r
+                Players[i]->Keys[o] = 0;\r
+            }\r
+        }\r
+        for(o = 0; o < NUM_KEYS; o++)\r
+            Players[i]->HeldKeys[o] = 0;\r
+        for(o = 0; o < NUM_KEYS; o++)\r
+        {\r
+            if(((Players[i]->KeyCodes[o] & 0xFF00) != 0) && (Players[i]->Keys[o] != 0))\r
+            {\r
+                for(u = 0; u < NUM_KEYS; u++)\r
+                {\r
+                    if((Players[i]->KeyCodes[u] == (Players[i]->KeyCodes[o] & 0x00FF)) || (Players[i]->KeyCodes[u] == ((Players[i]->KeyCodes[o] & 0xFF00) >> 8)))\r
+                    {\r
+                        Players[i]->Keys[u] = 0;\r
+                        Players[i]->HeldKeys[u] = 1;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void SetMode(unsigned char Mode)\r
+{\r
+    if(FullScreen != Mode)\r
+    {\r
+       SDL_WM_ToggleFullScreen(VBuffer);\r
+       FullScreen = Mode;\r
+    }\r
+    if(FullScreen == 0)\r
+       SDL_ShowCursor(SDL_ENABLE);\r
+    else\r
+       SDL_ShowCursor(SDL_DISABLE);\r
+}\r
+\r
+void MessageBox(unsigned char *Buffer)\r
+{\r
+    DBFRect(68, 88, 252, 112, MakeColor(255, 0, 0));\r
+    DBFRect(69, 89, 251, 111, MakeColor(0, 0, 0));\r
+    DBPrint(Buffer, 70, 90, 255);\r
+    DisplayDB();\r
+    while(KeyTable[57] == 1) GetEvents();\r
+    while(KeyTable[57] == 0) GetEvents();\r
+}\r
+\r
+unsigned char LoadMod(KvidFile *ModFile)\r
+{\r
+    unsigned short i, o, MaxPattern, Granularity, BkOffset;\r
+    unsigned long Signature, BkAU, u;\r
+    unsigned char Bytes[4], NumSamples, OldMod;\r
+    ModEvent *Buffer;\r
+\r
+    for(i = 0; i < MAX_SAMPLES; i++)\r
+    {\r
+        if(Samples[i].Allocated != 0)\r
+        {\r
+            Samples[i].Allocated = 0;\r
+            free(Samples[i].Buffer);\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_CHANNELS; i++)\r
+    {\r
+        memset((void *)&Channels[i], 0, sizeof(ModChannel));\r
+    }\r
+    if((ModFile->DataFile == 1) || (ModFile->Parent != NULL))\r
+    {\r
+        BkAU = ModFile->CurAU;\r
+        BkOffset = ModFile->Offset;\r
+    } else {\r
+        BkAU = ftell(ModFile->FilePtr);\r
+    }\r
+    FileSkip(ModFile, 1080);\r
+    Signature = FileGetChar(ModFile);\r
+    for(i = 0; i < 3; i++)\r
+    {\r
+        Signature <<= 8;\r
+        Signature += FileGetChar(ModFile);\r
+    }\r
+    if((ModFile->DataFile == 1) || (ModFile->Parent != NULL))\r
+    {\r
+        ModFile->CurAU = BkAU;\r
+        ModFile->Offset = BkOffset;\r
+        ModFile->ReSeek = 1;\r
+    } else {\r
+        fseek(ModFile->FilePtr, BkAU, SEEK_SET);\r
+    }\r
+    FileSkip(ModFile, 20);\r
+    ModChannels = 0;\r
+    if((Signature == 0x4D2E4B2E) || (Signature == 0x4D214B21))          //"M.K." or "M!K!"\r
+        ModChannels = 4;\r
+    if(Signature == 0x3643484E)                                         //"6CHN"\r
+        ModChannels = 6;\r
+    if(Signature == 0x3843484E)                                         //"8CHN"\r
+        ModChannels = 8;\r
+    if(Signature == 0x31324348)                                         //"12CH"\r
+        ModChannels = 12;\r
+    if(ModChannels == 0)\r
+    {\r
+        ModChannels = 4;\r
+        NumSamples = 15;\r
+        OldMod = 1;\r
+    } else {\r
+        NumSamples = 31;\r
+        OldMod = 0;\r
+    }\r
+    for(i = 0; i < NumSamples; i++)\r
+    {\r
+        FileSkip(ModFile, 22);\r
+        Samples[i].SampleLen = ((FileGetChar(ModFile) << 8) + FileGetChar(ModFile)) << 1;\r
+        Samples[i].FineTune = FileGetChar(ModFile) & 0x0F;\r
+        Samples[i].Volume = FileGetChar(ModFile);\r
+        Samples[i].LoopStart = (FileGetChar(ModFile) << 8) + FileGetChar(ModFile);\r
+        Samples[i].LoopLen = (FileGetChar(ModFile) << 8) + FileGetChar(ModFile);\r
+        if(OldMod == 0)\r
+        {\r
+            Samples[i].LoopStart <<= 1;\r
+            Samples[i].LoopLen <<= 1;\r
+        }\r
+    }\r
+    ModLen = FileGetChar(ModFile);\r
+    if(ModLen > 128)\r
+        ModLen = 128;\r
+    ModRepeat = FileGetChar(ModFile);\r
+    MaxPattern = 0;\r
+    for(i = 0; i < 128; i++)\r
+    {\r
+        if((PatternOrder[i] = FileGetChar(ModFile)) > MaxPattern)\r
+            MaxPattern = PatternOrder[i];\r
+    }\r
+    if(NumSamples > 15)\r
+        FileSkip(ModFile, 4);\r
+    Granularity = 64 * ModChannels;\r
+    for(i = 0; i <= MaxPattern; i++)\r
+    {\r
+        for(o = 0; o < Granularity; o++)\r
+        {\r
+            Buffer = &Patterns[(i * Granularity) + o];\r
+            FileRead((void *)Bytes, 4, ModFile);\r
+            Buffer->Period = ((Bytes[0] & 0x0F) << 8) | Bytes[1];\r
+            Buffer->Sample = (Bytes[0] & 0xF0) | ((Bytes[2] & 0xF0) >> 4);\r
+            Buffer->Effect = Bytes[2] & 0x0F;\r
+            Buffer->EffectData = Bytes[3];\r
+        }\r
+    }\r
+    for(i = 0; i < NumSamples; i++)\r
+    {\r
+        if(Samples[i].SampleLen > 0)\r
+        {\r
+            //Samples[i].SampleLen = SoundCaches[15]->Length;\r
+            if((Samples[i].Buffer = (unsigned char *)malloc(Samples[i].SampleLen)) == NULL)\r
+                return(2);\r
+            FileRead((void *)Samples[i].Buffer, Samples[i].SampleLen, ModFile);\r
+            //for(u = 0; u < Samples[i].SampleLen; u++)\r
+            //    Samples[i].Buffer[u] = (signed char)((signed short)(SoundCaches[15]->SoundBuffer[u]) - 128);\r
+            Samples[i].Allocated = 1;\r
+        }\r
+    }\r
+    ModPattern = 0;\r
+    ModRow = 0;\r
+    ModOffset = 0;\r
+    ModBPM = 125;\r
+    ModTPD = 6;\r
+    return(0);\r
+}\r
+\r
+unsigned char LoadSprite(unsigned char *ID, unsigned short CacheNum)\r
+{\r
+    unsigned short i, o, Found;\r
+    KvidFile SpriteFile;\r
+\r
+    if(OpenFile(ID, &SpriteFile) == 0)\r
+        return(1);\r
+    FileRead((void *)&Caches[CacheNum]->w, 2, &SpriteFile);\r
+    FileRead((void *)&Caches[CacheNum]->h, 2, &SpriteFile);\r
+    FileRead((void *)&Caches[CacheNum]->NumFrames, 1, &SpriteFile);\r
+    FileRead((void *)&Caches[CacheNum]->AnimDelay, 1, &SpriteFile);\r
+    if((Caches[CacheNum]->cx = (signed short *)malloc(Caches[CacheNum]->NumFrames * 2)) == NULL)\r
+        return(2);\r
+    if((Caches[CacheNum]->cy = (signed short *)malloc(Caches[CacheNum]->NumFrames * 2)) == NULL)\r
+        return(2);\r
+    if((Caches[CacheNum]->Frames = (unsigned char **)malloc(Caches[CacheNum]->NumFrames * 4)) == NULL)\r
+        return(2);\r
+    for(o = 0; o < Caches[CacheNum]->NumFrames; o++)\r
+    {\r
+        FileRead((void *)&Caches[CacheNum]->cx[o], 2, &SpriteFile);\r
+        FileRead((void *)&Caches[CacheNum]->cy[o], 2, &SpriteFile);\r
+        if((Caches[CacheNum]->Frames[o] = (unsigned char *)malloc(Caches[CacheNum]->w * Caches[CacheNum]->h * 4)) == NULL)\r
+            return(2);\r
+        FileRead((void *)Caches[CacheNum]->Frames[o], Caches[CacheNum]->w * Caches[CacheNum]->h * 4, &SpriteFile);\r
+    }\r
+    FileClose(&SpriteFile);\r
+    return(0);\r
+}\r
+\r
+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 Transparent)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = 0; i < MAX_SPRITES; i++)\r
+    {\r
+        if(Sprites[i]->Used == 0)\r
+        {\r
+            Sprites[i]->x = x;\r
+            Sprites[i]->y = y;\r
+            Sprites[i]->xv = xv;\r
+            Sprites[i]->yv = yv;\r
+            Sprites[i]->AnimTimer = 0;\r
+            Sprites[i]->AnimCount = AnimCount;\r
+            Sprites[i]->AnimDelay = Caches[Template]->AnimDelay;\r
+            Sprites[i]->CurFrame = StartFrame;\r
+            Sprites[i]->Template = Template;\r
+            Sprites[i]->Transparent = Transparent;\r
+            Sprites[i]->Used = 1;\r
+            return(i);\r
+        }\r
+    }\r
+    return(0xFFFF);\r
+}\r
+\r
+void FillBuffer(void)\r
+{\r
+    unsigned short i, o;\r
+    unsigned long Offset;\r
+    signed short Data, Data2;\r
+    unsigned short ModBPD;\r
+    unsigned short SampleRate;\r
+    unsigned char Temp;\r
+    float Amp;\r
+    ModEvent *Buffer;\r
+\r
+    for(i = 0; i < SB_SIZE >> 1; i++)\r
+    {\r
+        SoundBuffer[i] = 128;\r
+    }\r
+    for(i = 0; i < MAX_SOUNDS; i++)\r
+    {\r
+        if(Sounds[i].Playing == 1)\r
+        {\r
+            for(o = 0; o < SB_SIZE >> 1; o++)\r
+            {\r
+                Sounds[i].PitchError += Sounds[i].Pitch;\r
+                while(Sounds[i].PitchError >= SBSampleRate)\r
+                {\r
+                    Sounds[i].PitchError -= SBSampleRate;\r
+                    Sounds[i].Offset++;\r
+                }\r
+                if(Sounds[i].Offset >= SoundCaches[Sounds[i].Sound]->Length)\r
+                {\r
+                    if(Sounds[i].Repeat == 0)\r
+                    {\r
+                        Sounds[i].Playing = 0;\r
+                        break;\r
+                    } else {\r
+                        Sounds[i].Offset = 0;\r
+                    }\r
+                }\r
+                Data = ((signed short)SoundBuffer[o] - 128);\r
+                Data += (((signed short)(SoundCaches[Sounds[i].Sound]->SoundBuffer[Sounds[i].Offset] - 128) * Sounds[i].Volume) / 4);\r
+                if(Data > 127)\r
+                    Data = 127;\r
+                if(Data < -128)\r
+                    Data = -128;\r
+                SoundBuffer[o] = (unsigned char)(Data + 128);\r
+            }\r
+        }\r
+    }\r
+    if(ModPlaying != 0)\r
+    {\r
+        ModBPD = (SBSampleRate * 5 * ModTPD) / (ModBPM * 2);\r
+        if(KeyTable[5] == 1)\r
+            ModBPD >>= 1;\r
+        for(i = 0; i < SB_SIZE >> 1; i++)\r
+        {\r
+            Data2 = 0;\r
+            for(o = 0; o < ModChannels; o++)\r
+            {\r
+                if(ModOffset == 0)\r
+                {\r
+                    Buffer = &Patterns[(((PatternOrder[ModPattern] << 6) + ModRow) * ModChannels) + o];\r
+                    if(Buffer->Period != 0)\r
+                    {\r
+                        Channels[o].Playing = 1;\r
+                        Channels[o].OldPeriod = Channels[o].CurPeriod;\r
+                        Channels[o].Period = Channels[o].CurPeriod = Buffer->Period;\r
+                        Channels[o].Offset = 0;\r
+                        Channels[o].Looping = 0;\r
+                        Channels[o].Reminder = 0;\r
+                        Channels[o].Effect = 0;\r
+                        Channels[o].EffectData.b = 0;\r
+                    }\r
+                    if(Buffer->Sample != 0)\r
+                    {\r
+                        if((Samples[Buffer->Sample - 1].SampleLen > 0) && (Samples[Buffer->Sample - 1].Volume > 0))\r
+                        {\r
+                            Channels[o].Playing = 1;\r
+                            Channels[o].Sample = Buffer->Sample - 1;\r
+                            Channels[o].Volume = Channels[o].CurVolume = Samples[Buffer->Sample - 1].Volume;\r
+                            Channels[o].Offset = 0;\r
+                            Channels[o].Looping = 0;\r
+                            Channels[o].Reminder = 0;\r
+                            Channels[o].Effect = 0;\r
+                            Channels[o].EffectData.b = 0;\r
+                        } else {\r
+                            Channels[o].Playing = 0;\r
+                        }\r
+                    }\r
+                    Channels[o].Effect = Buffer->Effect;\r
+                    Channels[o].EffectData.b = Buffer->EffectData;\r
+                    if(Buffer->Effect == 4)\r
+                    {\r
+                        Channels[o].Oscillation = 1;\r
+                        if((Channels[o].EffectData.Nibbles.n1 != 0) && (Channels[o].EffectData.Nibbles.n2 != 0))\r
+                        {\r
+                            Channels[o].OscFreq = Channels[o].EffectData.Nibbles.n1;\r
+                            Channels[o].OscAmp = Channels[o].EffectData.Nibbles.n2;\r
+                        }\r
+                        if(Channels[o].OscNoTrig == 0)\r
+                            Channels[o].OscOffset = 0;\r
+                    } else {\r
+                        if((Buffer->Effect != 7) && (Buffer->Effect != 6))\r
+                            Channels[o].Oscillation = 0;\r
+                    }\r
+                    if(Buffer->Effect == 7)\r
+                    {\r
+                        Channels[o].Oscillation = 2;\r
+                        if((Channels[o].EffectData.Nibbles.n1 != 0) && (Channels[o].EffectData.Nibbles.n2 != 0))\r
+                        {\r
+                            Channels[o].OscFreq = Channels[o].EffectData.Nibbles.n1;\r
+                            Channels[o].OscAmp = Channels[o].EffectData.Nibbles.n2;\r
+                        }\r
+                        if(Channels[o].OscNoTrig == 0)\r
+                            Channels[o].OscOffset = 0;\r
+                    } else {\r
+                        if((Buffer->Effect != 4) && (Buffer->Effect != 6))\r
+                            Channels[o].Oscillation = 0;\r
+                    }\r
+                    if(Buffer->Effect == 6)\r
+                        Channels[o].Effect = 10;\r
+                    if(Buffer->Effect == 9)\r
+                        Channels[o].Offset = Buffer->EffectData << 8;\r
+                    if(Buffer->Effect == 12)\r
+                    {\r
+                        Channels[o].Volume = Buffer->EffectData;\r
+                        if(Channels[o].Volume > 64)\r
+                            Channels[o].Volume = 64;\r
+                        Channels[o].CurVolume = Channels[o].Volume;\r
+                    }\r
+                    if(Buffer->Effect == 14)\r
+                    {\r
+                        if((Channels[o].EffectData.Nibbles.n1 = 4) || (Channels[o].EffectData.Nibbles.n1 = 7))\r
+                        {\r
+                            Channels[o].OscWave = Channels[o].EffectData.Nibbles.n2 & 3;\r
+                            Channels[o].OscOffset = 0;\r
+                            if(Channels[o].OscWave == 3)\r
+                                Channels[o].OscWave = rand() % 3;\r
+                            if(Channels[o].EffectData.Nibbles.n2 > 3)\r
+                                Channels[o].OscNoTrig = 1;\r
+                            else\r
+                                Channels[o].OscNoTrig = 0;\r
+                        }\r
+                    }\r
+                    if(Buffer->Effect == 15)\r
+                    {\r
+                        if(Buffer->EffectData <= 32)\r
+                            ModTPD = Buffer->EffectData;\r
+                        else\r
+                            ModBPM = Buffer->EffectData;\r
+                        ModBPD = ((5 * SBSampleRate) * ModTPD) / (ModBPM * 2);\r
+                    }\r
+                }\r
+                if(Channels[o].Playing != 0)\r
+                {\r
+                    SampleRate = 7093789 / (Channels[o].CurPeriod << 1);\r
+                    if(KeyTable[6] == 1)\r
+                        SampleRate <<= 1;\r
+                    Channels[o].Reminder += SampleRate;\r
+                    if(Channels[o].Reminder >= SBSampleRate)\r
+                    {\r
+                        Channels[o].LastSample = Samples[Channels[o].Sample].Buffer[Channels[o].Offset];\r
+                        while(Channels[o].Reminder >= SBSampleRate)\r
+                        {\r
+                            Channels[o].Reminder -= SBSampleRate;\r
+                            Channels[o].Offset++;\r
+                        }\r
+                    }\r
+                    if(Channels[o].Looping != 0)\r
+                    {\r
+                        if(Channels[o].Offset >= Samples[Channels[o].Sample].LoopStart + Samples[Channels[o].Sample].LoopLen)\r
+                            Channels[o].Offset = Samples[Channels[o].Sample].LoopStart;\r
+                    } else {\r
+                        if(Channels[o].Offset >= Samples[Channels[o].Sample].SampleLen)\r
+                        {\r
+                            if(Samples[Channels[o].Sample].LoopLen > 2)\r
+                            {\r
+                                Channels[o].Looping = 1;\r
+                                Channels[o].Offset = Samples[Channels[o].Sample].LoopStart;\r
+                            } else {\r
+                                Channels[o].Playing = 0;\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+                if(Channels[o].Playing != 0)\r
+                {\r
+                    Data = (signed short)Samples[Channels[o].Sample].Buffer[Channels[o].Offset];\r
+                    Data2 += (Data * Channels[o].CurVolume) / 256;\r
+                    if(Channels[o].Oscillation == 1)\r
+                    {\r
+                        Amp = (WaveForms[Channels[o].OscWave][(unsigned short)Channels[o].OscOffset] * (float)Channels[o].OscAmp) / 32;\r
+                        Channels[o].CurPeriod = (unsigned short)((double)Channels[o].Period * pow(2, (double)(Amp / 12)));\r
+                        Channels[o].OscOffset += ((float)Channels[o].OscFreq * (float)ModTPD * 360) / (64 * ModBPD);\r
+                        if(Channels[o].OscOffset >= 360)\r
+                            Channels[o].OscOffset -= 360;\r
+                    }\r
+                    if(Channels[o].Oscillation == 2)\r
+                    {\r
+                        Amp = WaveForms[Channels[o].OscWave][(unsigned short)Channels[o].OscOffset] * (float)Channels[o].OscAmp * (float)(ModTPD - 1);\r
+                        Channels[o].CurVolume = (unsigned char)((signed char)Channels[o].Volume + (signed char)Amp);\r
+                        if((Amp > 0) && (Channels[o].CurVolume > 64))\r
+                            Channels[o].CurVolume = 64;\r
+                        if((Amp < 0) && (Channels[o].CurVolume > 64))\r
+                            Channels[o].CurVolume = 0;\r
+                        Channels[o].OscOffset += ((float)Channels[o].OscFreq * (float)ModTPD * 360) / (64 * ModBPD);\r
+                        if(Channels[o].OscOffset >= 360)\r
+                            Channels[o].OscOffset -= 360;\r
+                    }\r
+                    if(Channels[o].Effect == 0)\r
+                    {\r
+                        if(ModOffset == (unsigned short)(ModBPD / 3))\r
+                            Channels[o].CurPeriod = (unsigned short)((double)Channels[o].Period * pow(2, (double)Channels[o].EffectData.Nibbles.n1 / 12));\r
+                        if(ModOffset == (unsigned short)((2 * ModBPD) / 3))\r
+                            Channels[o].CurPeriod = (unsigned short)((double)Channels[o].Period * pow(2, (double)Channels[o].EffectData.Nibbles.n2 / 12));\r
+                    }\r
+                    if(Channels[o].Effect == 1)\r
+                    {\r
+                        Channels[o].CurPeriod = Channels[o].Period - (unsigned short)(((unsigned long)Channels[o].EffectData.b * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
+                        if((signed short)Channels[o].CurPeriod < 113)\r
+                            Channels[o].CurPeriod = 113;\r
+                    }\r
+                    if(Channels[o].Effect == 2)\r
+                    {\r
+                        Channels[o].CurPeriod = Channels[o].Period + (unsigned short)(((unsigned long)Channels[o].EffectData.b * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
+                        if(Channels[o].CurPeriod > 856)\r
+                            Channels[o].CurPeriod = 856;\r
+                    }\r
+                    if(Channels[o].Effect == 3)\r
+                    {\r
+                        if(Channels[o].OldPeriod > Channels[o].Period)\r
+                        {\r
+                            Channels[o].CurPeriod = Channels[o].OldPeriod - (unsigned short)(((unsigned long)Channels[o].EffectData.b * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
+                            if((signed short)Channels[o].CurPeriod < Channels[o].Period)\r
+                                Channels[o].CurPeriod = Channels[o].Period;\r
+                        } else {\r
+                            Channels[o].CurPeriod = Channels[o].OldPeriod + (unsigned short)(((unsigned long)Channels[o].EffectData.b * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
+                            if(Channels[o].CurPeriod > Channels[o].Period)\r
+                                Channels[o].CurPeriod = Channels[o].Period;\r
+                        }\r
+                    }\r
+                    if((Channels[o].Effect == 10) && (Channels[o].EffectData.Nibbles.n1 > 0))\r
+                    {\r
+                        Channels[o].CurVolume = Channels[o].Volume + (unsigned char)(((unsigned long)Channels[o].EffectData.Nibbles.n1 * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
+                        if(Channels[o].CurVolume > 64)\r
+                            Channels[o].CurVolume = 64;\r
+                    } else {\r
+                        if((Channels[o].Effect == 10) && (Channels[o].EffectData.Nibbles.n2 > 0))\r
+                        {\r
+                            Channels[o].CurVolume = Channels[o].Volume - (unsigned char)(((unsigned long)Channels[o].EffectData.Nibbles.n2 * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
+                            if(Channels[o].CurVolume > 64)\r
+                                Channels[o].CurVolume = 0;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            if(++ModOffset >= ModBPD)\r
+            {\r
+                ModRow++;\r
+                Temp = 0;\r
+                for(o = 0; o < ModChannels; o++)\r
+                {\r
+                    if(Channels[o].Effect == 11)\r
+                    {\r
+                        ModRow = 0;\r
+                        ModPattern = Channels[o].EffectData.b;\r
+                    }\r
+                    if((Channels[o].Effect == 13) && (Temp == 0))\r
+                    {\r
+                        if(++ModPattern >= ModLen)\r
+                        {\r
+                            if(ModRepeat >= ModLen)\r
+                                ModPattern = 0;\r
+                            else\r
+                                ModPattern = ModRepeat;\r
+                        }\r
+                        ModRow = (Channels[o].EffectData.Nibbles.n1 * 10) + Channels[o].EffectData.Nibbles.n2;\r
+                        Temp = 1;\r
+                    }\r
+                }\r
+                ModOffset = 0;\r
+                if(ModRow >= 64)\r
+                {\r
+                    ModRow = 0;\r
+                    if(++ModPattern >= ModLen)\r
+                    {\r
+                        if(ModRepeat >= ModLen)\r
+                            ModPattern = 0;\r
+                        else\r
+                            ModPattern = ModRepeat;\r
+                    }\r
+                }\r
+            }\r
+            Data = (signed short)SoundBuffer[i] - 128;\r
+            Data += Data2;\r
+            if(Data > 127)\r
+                Data = 127;\r
+            if(Data < -128)\r
+                Data = -128;\r
+            SoundBuffer[i] = (unsigned char)(Data + 128);\r
+        }\r
+    }\r
+    BufferReady = 0;\r
+}\r
+\r
+unsigned long GetString(unsigned short StringNum, unsigned short *Length)\r
+{\r
+    unsigned long Offset, Offset2;\r
+    unsigned short Count;\r
+\r
+    Offset = 0;\r
+    Count = 0;\r
+    while(Count < StringNum)\r
+    {\r
+        if(Strings[Offset++] == 0)\r
+            Count++;\r
+    }\r
+    Offset2 = Offset;\r
+    while(Strings[Offset2++] != 0);\r
+    if(Length != NULL)\r
+        *Length = Offset2 - Offset;\r
+    return(Offset);\r
+}\r
+\r
+void LoadMenu(unsigned short MenuNum)\r
+{\r
+    unsigned long Offset;\r
+    unsigned short i, o;\r
+    unsigned short NumItems, CurItem;\r
+    unsigned char DataLength;\r
+\r
+    Offset = 0;\r
+    CurItem = 0;\r
+    MenuID = MenuNum;\r
+    for(i = 0; i <= MenuNum; i++)\r
+    {\r
+        NumItems = *(unsigned short *)(MenuBuffer + Offset);\r
+        Offset += 2;\r
+        if(i == MenuNum)\r
+            NumMenuItems = NumItems;\r
+        for(o = 0; o < NumItems; o++)\r
+        {\r
+            DataLength = MenuBuffer[Offset++];\r
+            if(i == MenuNum)\r
+            {\r
+                MenuItems[0][CurItem] = MenuBuffer + Offset;\r
+                Offset += DataLength;\r
+                strcpy(MenuItems[1][CurItem++], Strings + GetString(*(unsigned short *)(MenuBuffer + Offset - 2), NULL));\r
+            } else {\r
+                Offset += DataLength;\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void LoadLayout(unsigned char NumPlayers)\r
+{\r
+    unsigned char i;\r
+    unsigned short o, Buffer[18];\r
+    KvidFile LayoutFile;\r
+\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+        Players[i]->Visual = 0;\r
+    if(OpenFile("Layouts", &LayoutFile) == 0)\r
+        return;\r
+    for(i = 0; i < NumPlayers - 1; i++)\r
+    {\r
+        FileSkip(&LayoutFile, 36 * (i + 1));\r
+    }\r
+    for(i = 0; i < NumPlayers; i++)\r
+    {\r
+        FileRead((void *)&Buffer, 36, &LayoutFile);\r
+        Players[i]->Visual = 1;\r
+        Players[i]->VPointX1 = Buffer[0];\r
+        Players[i]->VPointY1 = Buffer[1];\r
+        Players[i]->VPointX2 = Buffer[2];\r
+        Players[i]->VPointY2 = Buffer[3];\r
+        Players[i]->AMeterX1 = Buffer[4];\r
+        Players[i]->AMeterY1 = Buffer[5];\r
+        Players[i]->AMeterX2 = Buffer[6];\r
+        Players[i]->AMeterY2 = Buffer[7];\r
+        Players[i]->LMeterX1 = Buffer[8];\r
+        Players[i]->LMeterY1 = Buffer[9];\r
+        Players[i]->LMeterX2 = Buffer[10];\r
+        Players[i]->LMeterY2 = Buffer[11];\r
+        Players[i]->lx = Buffer[12];\r
+        Players[i]->ly = Buffer[13];\r
+        Players[i]->kx = Buffer[14];\r
+        Players[i]->ky = Buffer[15];\r
+        Players[i]->cx = Buffer[16];\r
+        Players[i]->cy = Buffer[17];\r
+        for(o = 0; o < NUM_MASKS; o++)\r
+        {\r
+            if(Players[i]->Masks[o].Buffer != NULL)\r
+                free(Players[i]->Masks[o].Buffer);\r
+            Players[i]->Masks[o].Buffer = (unsigned char *)malloc((Buffer[2] - Buffer[0] + 1) * (Buffer[3] - Buffer[1] + 1) * 4);\r
+        }\r
+    }\r
+    FileClose(&LayoutFile);\r
+}\r
+\r
+unsigned char InitVar(void)\r
+{\r
+    unsigned short i, o;\r
+    KvidFile KeyFile;\r
+\r
+    LoadLayout(2);\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        if(i == 0)\r
+        {\r
+            if(OpenFile("player1.ctr", &KeyFile) == 0)\r
+                return(1);\r
+        }\r
+        if(i == 1)\r
+        {\r
+            if(OpenFile("player2.ctr", &KeyFile) == 0)\r
+                return(1);\r
+        }\r
+        if(i < 2)\r
+        {\r
+            for(o = 0; o < 9; o++)\r
+                FileRead((void *)&Players[i]->KeyCodes[o], 2, &KeyFile);\r
+            FileClose(&KeyFile);\r
+        }\r
+        Players[i]->Angle = 0;\r
+        Players[i]->AngleVel = 0;\r
+        Players[i]->Dir = 0;\r
+        Players[i]->MaxHealth = 500;\r
+        Players[i]->Health = Players[0]->MaxHealth;\r
+        Players[i]->Kills = 0;\r
+        Players[i]->Lives = 5;\r
+        Players[i]->CurWeapon = 0;\r
+        /*Players[i]->Masks[0].Method = 1;\r
+        Players[i]->Masks[0].Effects[0] = 2;*/\r
+        for(o = 0; o < NUM_WEAPONS; o++)\r
+        {\r
+            PWeapons[i][o]->Weapon = o;\r
+            PWeapons[i][o]->Used = 1;\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        for(o = 0; o < NUM_WEAPONS; o++)\r
+        {\r
+            if((Players[i]->Used == 1) && (PWeapons[i][o]->Used == 1))\r
+            {\r
+                PWeapons[i][o]->AmmoLeft = Weapons[PWeapons[i][o]->Weapon]->Ammo;\r
+                PWeapons[i][o]->FireTimer = 0;\r
+                PWeapons[i][o]->ReloadTimer = 0;\r
+                PWeapons[i][o]->NumClips = Weapons[PWeapons[i][o]->Weapon]->MaxClips;\r
+            }\r
+        }\r
+    }\r
+    BGSprite = 53;\r
+    BGFrame = 0;\r
+    FogSprite = 48;\r
+    FogX = 0;\r
+    FogY = 0;\r
+    return(0);\r
+}\r
+\r
+unsigned char Init(unsigned short *Result)\r
+{\r
+    unsigned short i, o;\r
+    unsigned char Buffer[80], InpBuffer, BufferPos, Finished, Major, Minor;\r
+    unsigned long LastPos, Offset, Size, u, BkAU;\r
+    unsigned short DataLength, Count, BkOffset;\r
+    KvidFile OpenedFile, OpenedFile2;\r
+    KvidFile SoundFile;\r
+\r
+    printf("Initializing...\n");\r
+    MainDat = NULL;\r
+    if((OpenDatFile("kvid.dat", &DataFile) == 0) || (DataFile.CanWrite == 0))\r
+        return(3);\r
+    MainDat = &DataFile;\r
+    if(DebugMode != 0)\r
+        printf("Initializing double buffer...\n");\r
+    DBSetClip(0, 0, 319, 199);\r
+    if(DebugMode != 0)\r
+        printf("Initializing level...\n");\r
+    MaxLW = 3200;\r
+    MaxLH = 2000;\r
+    for(i = 0; i < NUM_PLANES; i++)\r
+    {\r
+        if((LevelBuffer[i] = (unsigned char *)malloc(MaxLW * MaxLH * ((i == 0)?4:1))) == NULL)\r
+            return(2);\r
+    }\r
+    if(DebugMode != 0)\r
+        printf("Initializing variables...\n");\r
+    for(i = 0; i < MAX_HITTESTS; i++)\r
+    {\r
+        HitTests[i] = 0xFFFF;\r
+    }\r
+    for(i = 0; i < MAX_PIXELS; i++)\r
+    {\r
+        if((Pixels[i] = (Pixel *)malloc(sizeof(Pixel))) == NULL)\r
+            return(2);\r
+        Pixels[i]->Used = 0;\r
+    }\r
+    for(i = 0; i < MAX_SPRITES; i++)\r
+    {\r
+        if((Sprites[i] = (Sprite *)malloc(sizeof(Sprite))) == NULL)\r
+            return(2);\r
+        Sprites[i]->Used = 0;\r
+    }\r
+    for(i = 0; i < MAX_OBJECTS; i++)\r
+    {\r
+        if((Objects[i] = (Object *)malloc(sizeof(Object))) == NULL)\r
+            return(2);\r
+        Objects[i]->Used = 0;\r
+    }\r
+    for(i = 0; i < MAX_OBJLISTS; i++)\r
+    {\r
+        if((ObjectLists[i] = (ObjectList *)malloc(sizeof(ObjectList))) == NULL)\r
+            return(2);\r
+        ObjectLists[i]->Used = 0;\r
+    }\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        if((Players[i] = (Player *)malloc(sizeof(Player))) == NULL)\r
+            return(2);\r
+        Players[i]->Used = 0;\r
+        Players[i]->Visual = 0;\r
+        for(o = 0; o < NUM_MASKS; o++)\r
+        {\r
+            Players[i]->Masks[o].Buffer = NULL;\r
+            Players[i]->Masks[o].Method = 0;\r
+            for(u = 0; u < 16; u++)\r
+                Players[i]->Masks[o].Effects[u] = 0;\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        for(o = 0; o < NUM_WEAPONS; o++)\r
+        {\r
+            if((PWeapons[i][o] = (PWeapon *)malloc(sizeof(PWeapon))) == NULL)\r
+                return(2);\r
+            PWeapons[i][o]->Used = 0;\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_LINES; i++)\r
+    {\r
+        if((Lines[i] = (Line *)malloc(sizeof(Line))) == NULL)\r
+            return(2);\r
+        Lines[i]->Used = 0;\r
+    }\r
+    for(i = 0; i < MAX_RASTERS; i++)\r
+    {\r
+        if((Rasters[i] = (Raster *)malloc(sizeof(Raster))) == NULL)\r
+            return(2);\r
+        Rasters[i]->Used = 0;\r
+    }\r
+    for(i = 0; i < MAX_MENUITEMS; i++)\r
+    {\r
+        if((MenuItems[1][i] = (unsigned char *)malloc(128)) == NULL)\r
+            return(2);\r
+    }\r
+    for(i = 0; i < MAX_SOUNDS; i++)\r
+    {\r
+        Sounds[i].Playing = 0;\r
+    }\r
+    if((MenuBuffer = (unsigned char *)malloc(16384)) == NULL)\r
+        return(2);\r
+    if((TextBuffer = (unsigned char *)malloc(500)) == NULL)\r
+        return(2);\r
+    if((KeyboardBuffer = (unsigned char *)malloc(500)) == NULL)\r
+        return(2);\r
+    if((LevelFileName = (unsigned char *)malloc(100)) == NULL)\r
+        return(2);\r
+    if((Patterns = (ModEvent *)malloc(MAX_PATTERNS * 512 * sizeof(ModEvent))) == NULL)\r
+        return(2);\r
+    if((SoundBuffer = (unsigned char *)malloc(SB_SIZE >> 1)) == NULL)\r
+        return(2);\r
+    for(i = 0; i < SB_SIZE >> 1; i++)\r
+        SoundBuffer[i] = 128;\r
+    TransOps[0] = ColorAdd;\r
+    TransOps[1] = ColorSub;\r
+    TransOps[2] = ColorAvr;\r
+    TransOps[3] = ColorSpc;\r
+    TransOps[4] = ColorFul;\r
+    Gravity = 0.02;\r
+    LevelWidth = 640;\r
+    LevelHeight = 400;\r
+    FrameRate = 50;\r
+    DSPAddress = 0x220;\r
+    DMAChannel = 1;\r
+    IRQLine = 5;\r
+    ModPlaying = 0;\r
+    MenuActive = 0;\r
+    EmptyKeyBuffer();\r
+    srand((unsigned int)time(NULL));\r
+    for(i = 0; i < 360; i++)\r
+    {\r
+        Sine[i] = sin(((float)i / 180) * M_PI);\r
+        Cosine[i] = cos(((float)i / 180) * M_PI);\r
+        PreSine[i] = sin(((double)i / 90) * M_PI_2);\r
+        PreCosine[i] = cos(((double)i / 90) * M_PI_2);\r
+        WaveForms[0][i] = sin(((float)i / 180) * M_PI);\r
+        WaveForms[1][i] = (float)(359 - i) / 359;\r
+        WaveForms[2][i] = (i < 180)?1:0;\r
+        WaveForms[3][i] = (float)i / 359;\r
+        WaveForms[4][i] = (i < 180)?((float)i / 179):((float)(179 - (i - 180)) / 179);\r
+    }\r
+    for(i = 0; i < MAX_SAMPLES; i++)\r
+    {\r
+        Samples[i].Allocated = 0;\r
+    }\r
+    if(DebugMode != 0)\r
+        printf("Loading data...\n");\r
+    if(OpenFile("Layouts", &OpenedFile) == 0)\r
+        return(4);\r
+    FileClose(&OpenedFile);\r
+    if(DebugMode != 0)\r
+        printf("Loading menus\n");\r
+    if(OpenFile("MenuData", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)&Count, 2, &OpenedFile);\r
+    Offset = 0;\r
+    for(i = 0; i < Count; i++)\r
+    {\r
+        FileRead((void *)&DataLength, 2, &OpenedFile);\r
+        *(unsigned short *)(MenuBuffer + Offset) = DataLength;\r
+        Offset += 2;\r
+        for(o = 0; o < DataLength; o++)\r
+        {\r
+            FileRead((void *)&InpBuffer, 1, &OpenedFile);\r
+            MenuBuffer[Offset++] = InpBuffer;\r
+            FileRead((void *)(MenuBuffer + Offset), (unsigned long)InpBuffer, &OpenedFile);\r
+            Offset += InpBuffer;\r
+        }\r
+    }\r
+    FileClose(&OpenedFile);\r
+    if(DebugMode != 0)\r
+        printf("Loading palette...\n");\r
+    if(OpenFile("DefaultPalette", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)Palette, sizeof(Pal) * NUM_COLORS, &OpenedFile);\r
+    FileClose(&OpenedFile);\r
+    if(DebugMode != 0)\r
+        printf("Loading color info...\n");\r
+    if(OpenFile("ColorInfo", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)ColorInfo, NUM_COLORS, &OpenedFile);\r
+    FileClose(&OpenedFile);\r
+    if(DebugMode != 0)\r
+        printf("Loading ASCII Table...\n");\r
+    if(OpenFile("AsciiConv", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)AsciiTable, 512, &OpenedFile);\r
+    FileClose(&OpenedFile);\r
+    if(OpenFile("MainAscii", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)AsciiTable2, 256, &OpenedFile);\r
+    FileClose(&OpenedFile);\r
+    if(DebugMode != 0)\r
+        printf("Loading strings...\n");\r
+    if(OpenFile("Strings", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)&LastPos, 4, &OpenedFile);\r
+    if((Strings = (unsigned char *)malloc((unsigned short)LastPos)) == NULL)\r
+        return(2);\r
+    for(Offset = 0; Offset < LastPos; Offset++)\r
+        Strings[Offset] = FileGetChar(&OpenedFile);\r
+    FileClose(&OpenedFile);\r
+    if(PLAY_TIME > 0)\r
+    {\r
+        if((OpenFile("BetaTime", &OpenedFile) == 0) || (OpenedFile.CanWrite == 0))\r
+            return(4);\r
+        FileRead((void *)&Count, 2, &OpenedFile);\r
+        if(Count != 0x464B)\r
+            return(4);\r
+        BkAU = OpenedFile.CurAU;\r
+        BkOffset = OpenedFile.Offset;\r
+        FileRead((void *)&NumPlays, 1, &OpenedFile);\r
+        if(NumPlays == 0)\r
+        {\r
+            printf("Your beta version has expired!\n");\r
+            return(4);\r
+        }\r
+        OpenedFile.CurAU = BkAU;\r
+        OpenedFile.Offset = BkOffset;\r
+        OpenedFile.ReSeek = 1;\r
+        FilePutChar(--NumPlays, &OpenedFile);\r
+        printf("You have %u time(s) left to play!\n", (unsigned short)NumPlays);\r
+    }\r
+    if(DebugMode != 0)\r
+        printf("Loading sprites...\n");\r
+    if(OpenFile("SpriteCache", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)&NumSprites, 2, &OpenedFile);\r
+    if((Caches = (Cache **)malloc(4 * NumSprites)) == NULL)\r
+        return(2);\r
+    for(i = 0; i < NumSprites; i++)\r
+    {\r
+        if((Caches[i] = (Cache *)malloc(sizeof(Cache))) == NULL)\r
+            return(2);\r
+        BufferPos = 0;\r
+        Finished = 0;\r
+        while(Finished == 0)\r
+        {\r
+            InpBuffer = FileGetChar(&OpenedFile);\r
+            if(InpBuffer == 0)\r
+            {\r
+                Buffer[BufferPos] = 0;\r
+                OpenedFile.ReSeek = 1;\r
+                switch(LoadSprite((unsigned char *)Buffer, i))\r
+                {\r
+                    case 1:\r
+                        return(4);\r
+                    case 2:\r
+                        return(2);\r
+                }\r
+                if(strcmp((char *)Buffer, (unsigned char *)"Spr_Font") == 0)\r
+                    FontSprite = i;\r
+                Finished = 1;\r
+            } else {\r
+                Buffer[BufferPos++] = InpBuffer;\r
+            }\r
+        }\r
+    }\r
+    FileClose(&OpenedFile);\r
+    if(DebugMode != 0)\r
+        printf("Loading classes...\n");\r
+    if(OpenFile("Classes", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)&NumClasses, 2, &OpenedFile);\r
+    if((Classes = (Class **)malloc(4 * NumClasses)) == NULL)\r
+        return(2);\r
+    for(i = 0; i < NumClasses; i++)\r
+    {\r
+        if((Classes[i] = (Class *)malloc(sizeof(Class))) == NULL)\r
+            return(2);\r
+        FileRead((void *)&Classes[i]->Scripts, 2 * NUM_SCRIPTS, &OpenedFile);\r
+        FileRead((void *)&Classes[i]->TickDelay, 1, &OpenedFile);\r
+        FileRead((void *)&Classes[i]->GravityMod, 2, &OpenedFile);\r
+        FileRead((void *)&Classes[i]->Sprite, 1, &OpenedFile);\r
+        FileRead((void *)&Classes[i]->StartFrame, 1, &OpenedFile);\r
+        FileRead((void *)&Classes[i]->RunHitTests, 1, &OpenedFile);\r
+        FileRead((void *)&Classes[i]->TouchDelay, 1, &OpenedFile);\r
+        FileRead((void *)&Classes[i]->TransSprite, 1, &OpenedFile);\r
+        FileRead((void *)&DataLength, 2, &OpenedFile);\r
+        if((Classes[i]->Code = (unsigned char *)malloc(DataLength)) == NULL)\r
+            return(2);\r
+        FileRead((void *)Classes[i]->Code, DataLength, &OpenedFile);\r
+    }\r
+    FileClose(&OpenedFile);\r
+    if(DebugMode != 0)\r
+        printf("Loading sounds...\n");\r
+    UseSound = 1;\r
+    FreeSound = 1;\r
+    if(OpenDatFile("kvidsnd.dat", &SoundFile) == 0)\r
+    {\r
+        printf("Couldn't find sound file KVIDSND.DAT!\nUsing no sound...\n");\r
+        UseSound = 0;\r
+        FreeSound = 0;\r
+    }\r
+    if(UseSound == 1)\r
+    {\r
+        if(OpenNestedFile("LoadSound", &OpenedFile, &SoundFile, NULL) == 0)\r
+        {\r
+            printf("Sound file corrupt!\nUsing no sound...\n");\r
+            UseSound = 0;\r
+            FreeSound = 0;\r
+        }\r
+    }\r
+    if(UseSound == 1)\r
+    {\r
+        FileRead((void *)&NumSounds, 2, &OpenedFile);\r
+        if((SoundCaches = (SoundCache **)malloc(NumSounds << 2)) == NULL)\r
+            return(2);\r
+        for(i = 0; i < NumSounds; i++)\r
+            SoundCaches[i] = NULL;\r
+        BufferPos = 0;\r
+        for(i = 0; i < NumSounds; i++)\r
+        {\r
+            OpenedFile.ReSeek = 1;\r
+            for(BufferPos = 0; (Buffer[BufferPos] = FileGetChar(&OpenedFile)) != 0; BufferPos++);\r
+            if(OpenNestedFile(Buffer, &OpenedFile2, &SoundFile, NULL) == 0)\r
+            {\r
+                printf("Sound file corrupt!\nUsing no sound...\n");\r
+                UseSound = 0;\r
+                break;\r
+            }\r
+            Offset = 0;\r
+            if((SoundCaches[i] = (SoundCache *)malloc(sizeof(SoundCache))) == NULL)\r
+                return(2);\r
+            FileRead((void *)&Size, 4, &OpenedFile2);\r
+            SoundCaches[i]->Length = Size;\r
+            if((SoundCaches[i]->SoundBuffer = (unsigned char *)malloc(Size)) == NULL)\r
+                return(2);\r
+            DataLength = 0;\r
+            for(u = 0; u <= Size; u++)\r
+            {\r
+                if(DataLength > 0)\r
+                {\r
+                    SoundCaches[i]->SoundBuffer[Offset++] = InpBuffer;\r
+                    DataLength--;\r
+                }\r
+                if(DataLength == 0)\r
+                {\r
+                    DataLength = 1;\r
+                    if((InpBuffer = FileGetChar(&OpenedFile2)) >= 192)\r
+                    {\r
+                        DataLength = InpBuffer - 191;\r
+                        InpBuffer = FileGetChar(&OpenedFile2);\r
+                    }\r
+                }\r
+            }\r
+            FileClose(&OpenedFile2);\r
+        }\r
+        FileClose(&OpenedFile);\r
+        FileClose(&SoundFile);\r
+    }\r
+    if(OpenFile("WeaponInfo", &OpenedFile) == 0)\r
+        return(4);\r
+    FileRead((void *)&NumWeapons, 2, &OpenedFile);\r
+    if((Weapons = (Weapon **)malloc(4 * NumWeapons)) == NULL)\r
+        return(2);\r
+    for(i = 0; i < NumWeapons; i++)\r
+    {\r
+        if((Weapons[i] = (Weapon *)malloc(sizeof(Weapon))) == NULL)\r
+            return(2);\r
+        FileRead((void *)&Weapons[i]->Class, 2, &OpenedFile);\r
+        FileRead((void *)&Weapons[i]->ReloadDelay, 2, &OpenedFile);\r
+        FileRead((void *)&Weapons[i]->FireDelay, 2, &OpenedFile);\r
+        FileRead((void *)&Weapons[i]->Ammo, 2, &OpenedFile);\r
+        FileRead((void *)&Weapons[i]->MaxClips, 2, &OpenedFile);\r
+        Weapons[i]->Name = 0;\r
+        FileRead((void *)&Weapons[i]->Name, 2, &OpenedFile);\r
+        Weapons[i]->Name = GetString((unsigned short)Weapons[i]->Name, (unsigned short *)&Weapons[i]->NameLength);\r
+    }\r
+    FileClose(&OpenedFile);\r
+    if(OpenFile("MainFont", &OpenedFile) == 0)\r
+        return(4);\r
+    if((FontBuffer = (unsigned short *)malloc(16384)) == NULL)\r
+        return(2);\r
+    memset((void *)FontBuffer, 0, 16384);\r
+    Offset = 0;\r
+    Size = 1;\r
+    for(i = 0; (i < 256) && (Size != 0); i++)\r
+    {\r
+        Size = 0;\r
+        FileRead((void *)&Size, 2, &OpenedFile);\r
+        FontBuffer[(i << 1)] = (unsigned short)Offset;\r
+        FontBuffer[(i << 1) + 1] = (unsigned short)Size;\r
+        for(o = 0; o < Size * 5; o++)\r
+        {\r
+            FileRead((void *)&FontBuffer[Offset + 512], 4, &OpenedFile);\r
+            Offset += 2;\r
+        }\r
+    }\r
+    FileClose(&OpenedFile);\r
+    if(DebugMode != 0)\r
+        printf("Initializing hardware...\n");\r
+    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0)\r
+    {\r
+       printf("%s\n", SDL_GetError());\r
+       return(0);\r
+    }\r
+    if((UseSound == 1) && (SBReset() != 0))\r
+    {\r
+        printf("Sound Blaster hardware reset failed!\n");\r
+        UseSound = 0;\r
+    }\r
+    if(UseSound == 1)\r
+    {\r
+       SBSampleRate = 44100;\r
+    } else {\r
+        printf("Using no sound...\n");\r
+    }\r
+    VBuffer = SDL_SetVideoMode(320, 200, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);\r
+    BPP = VBuffer->format->BytesPerPixel * 8;\r
+    if(BPP != 32)\r
+    {\r
+       printf("Video mode format mismatch (BPP = %i)\n", BPP);\r
+       return(1);\r
+    }\r
+    DblBuffer = VBuffer->pixels;\r
+    FullScreen = 0;\r
+    printf("Done!\n");\r
+/*  getch(); */\r
+    SetMode(1);\r
+    if(UseSound == 1)\r
+    {\r
+        ReadyBuffer = 0;\r
+        BufferReady = 0;\r
+        FillBuffer();\r
+        ReadyBuffer = 1;\r
+        StartPlayBack();\r
+    }\r
+    return(0xFF);\r
+}\r
+\r
+void Terminate(void)\r
+{\r
+    unsigned short i, o;\r
+\r
+    SetMode(0);\r
+    SDL_Quit();\r
+    FileClose(&DataFile);\r
+    MainDat = NULL;\r
+    for(i = 0; i < NUM_PLANES; i++)\r
+        free(LevelBuffer[i]);\r
+    if(FontBuffer != NULL)\r
+        free(FontBuffer);\r
+    if(FreeSound == 1)\r
+    {\r
+        for(i = 0; i < NumSounds; i++)\r
+        {\r
+            if(SoundCaches[i] != NULL)\r
+            {\r
+                free(SoundCaches[i]->SoundBuffer);\r
+                free(SoundCaches[i]);\r
+            }\r
+        }\r
+        free(SoundCaches);\r
+    }\r
+    if(UseSound == 1)\r
+        TerminatePlayBack();\r
+    for(i = 0; i < MAX_PIXELS; i++)\r
+    {\r
+        if(Pixels[i] != NULL)\r
+            free(Pixels[i]);\r
+    }\r
+    for(i = 0; i < NumSprites; i++)\r
+    {\r
+        if(Caches[i] != NULL)\r
+        {\r
+            if(Caches[i]->cx != NULL)\r
+                free(Caches[i]->cx);\r
+            if(Caches[i]->cy != NULL)\r
+                free(Caches[i]->cy);\r
+            if(Caches[i]->Frames != NULL)\r
+            {\r
+                for(o = 0; o < Caches[i]->NumFrames; o++)\r
+                {\r
+                    if(Caches[i]->Frames[o] != NULL)\r
+                        free(Caches[i]->Frames[o]);\r
+                }\r
+                free(Caches[i]->Frames);\r
+            }\r
+            free(Caches[i]);\r
+        }\r
+    }\r
+    if(Caches != NULL)\r
+        free(Caches);\r
+    for(i = 0; i < MAX_SPRITES; i++)\r
+    {\r
+        if(Sprites[i] != NULL)\r
+            free(Sprites[i]);\r
+    }\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        if(Players[i] != NULL)\r
+        {\r
+            for(o = 0; o < NUM_MASKS; o++)\r
+            {\r
+                if(Players[i]->Masks[o].Buffer != NULL)\r
+                    free(Players[i]->Masks[o].Buffer);\r
+            }\r
+            free(Players[i]);\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_OBJECTS; i++)\r
+    {\r
+        if(Objects[i] != NULL)\r
+            free(Objects[i]);\r
+    }\r
+    for(i = 0; i < NumClasses; i++)\r
+    {\r
+        if(Classes[i]->Code != NULL)\r
+            free(Classes[i]->Code);\r
+        if(Classes[i] != NULL)\r
+            free(Classes[i]);\r
+    }\r
+    if(Classes != NULL)\r
+        free(Classes);\r
+    for(i = 0; i < NumWeapons; i++)\r
+    {\r
+        if(Weapons[i] != NULL)\r
+            free(Weapons[i]);\r
+    }\r
+    if(Weapons != NULL)\r
+        free(Weapons);\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        for(o = 0; o < NUM_WEAPONS; o++)\r
+        {\r
+            if(PWeapons[i][o] != NULL)\r
+                free(PWeapons[i][o]);\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_LINES; i++)\r
+    {\r
+        if(Lines[i] != NULL)\r
+            free(Lines[i]);\r
+    }\r
+    for(i = 0; i < MAX_RASTERS; i++)\r
+    {\r
+        if(Rasters[i] != NULL)\r
+            free(Rasters[i]);\r
+    }\r
+    for(i = 0; i < MAX_MENUITEMS; i++)\r
+    {\r
+        if(MenuItems[1][i] != NULL)\r
+            free(MenuItems[1][i]);\r
+    }\r
+    if(Strings != NULL)\r
+        free(Strings);\r
+    if(MenuBuffer != NULL)\r
+        free(MenuBuffer);\r
+    if(TextBuffer != NULL)\r
+        free(TextBuffer);\r
+    if(KeyboardBuffer != NULL)\r
+        free(KeyboardBuffer);\r
+    if(LevelFileName != NULL)\r
+        free(LevelFileName);\r
+    if(SoundBuffer != NULL)\r
+        free(SoundBuffer);\r
+    if(Patterns != NULL)\r
+        free(Patterns);\r
+    for(i = 0; i < MAX_SAMPLES; i++)\r
+    {\r
+        if(Samples[i].Allocated != 0)\r
+            free(Samples[i].Buffer);\r
+    }\r
+}\r
+\r
+void HurtRadius(signed short x, signed short y, signed short StartDamage, signed short StopDamage, unsigned short StartDecRadius, unsigned short StopRadius, unsigned char Owner)\r
+{\r
+    unsigned short i;\r
+    signed long square, xdist, ydist;\r
+    unsigned short Radius, Sprite;\r
+    unsigned short Template;\r
+    signed short Damage;\r
+\r
+    for(i = 0; i < MAX_OBJECTS; i++)\r
+    {\r
+        if(Objects[i]->Used == 1)\r
+        {\r
+            if((Objects[i]->SpriteLink != 0xFFFF) && (Sprites[Objects[i]->SpriteLink]->Template != 0xFF))\r
+            {\r
+                Sprite = Objects[i]->SpriteLink;\r
+                Template = (unsigned short)Sprites[Sprite]->Template;\r
+                xdist = (signed long)(x - (signed short)Objects[i]->x + Caches[Template]->cx[Sprites[Sprite]->CurFrame]);\r
+                ydist = (signed long)(y - (signed short)Objects[i]->y + Caches[Template]->cy[Sprites[Sprite]->CurFrame]);\r
+                if(xdist < 0) xdist = 0;\r
+                if(ydist < 0) ydist = 0;\r
+                if(xdist > (signed long)Caches[Template]->w) xdist = (signed long)Caches[Template]->w;\r
+                if(ydist > (signed long)Caches[Template]->h) ydist = (signed long)Caches[Template]->h;\r
+                xdist += (signed long)Objects[i]->x - (signed long)Caches[Template]->cx[Sprites[Sprite]->CurFrame];\r
+                ydist += (signed long)Objects[i]->y - (signed long)Caches[Template]->cy[Sprites[Sprite]->CurFrame];\r
+            } else {\r
+                xdist = (signed long)Objects[i]->x;\r
+                ydist = (signed long)Objects[i]->y;\r
+            }\r
+            xdist = (signed long)(x - (signed short)xdist);\r
+            ydist = (signed long)(y - (signed short)ydist);\r
+            square = (xdist * xdist) + (ydist * ydist);\r
+            Radius = (unsigned short)sqrt((double)square);\r
+            if(Radius < StopRadius)\r
+            {\r
+                if(Radius < StartDecRadius)\r
+                {\r
+                    Damage = StartDamage;\r
+                } else {\r
+                    Damage = (unsigned short)((((float)(Radius - StartDecRadius) / (float)(StopRadius - StartDecRadius)) * (float)(StartDamage - StopDamage)) + StopDamage);\r
+                }\r
+                Regs[16] = (signed short)i;\r
+                Regs[17] = (signed short)Damage;\r
+                Regs[18] = (signed short)Owner;\r
+                Regs[19] = (signed short)Objects[i]->x;\r
+                Regs[20] = (signed short)Objects[i]->y;\r
+                Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Objects[i]->Class]->Scripts[3]);                        //TakeDamage\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+unsigned char SpritesOverlap(unsigned char Cache1, unsigned short Frame1, unsigned char Cache2, unsigned short Frame2, signed short dx, signed short dy)\r
+{\r
+    signed short x, y;\r
+    unsigned short w, h;\r
+    unsigned char *Buffer1;\r
+    unsigned char *Buffer2;\r
+    unsigned long Offset;\r
+    unsigned long Data;\r
+\r
+    Buffer1 = Caches[Cache1]->Frames[Frame1];\r
+    Buffer2 = Caches[Cache2]->Frames[Frame2];\r
+    dx += Caches[Cache1]->cx[Frame1];\r
+    dy += Caches[Cache1]->cy[Frame1];\r
+    dx -= Caches[Cache2]->cx[Frame2];\r
+    dy -= Caches[Cache2]->cy[Frame2];\r
+    w = Caches[Cache2]->w;\r
+    h = Caches[Cache2]->h;\r
+    Offset = 0;\r
+    y = dy;\r
+    for(y = -dy; y < (signed short)Caches[Cache1]->h - dy; y++)\r
+    {\r
+        if((y < (signed short)h) && (y >= 0))\r
+        {\r
+            for(x = -dx; x < (signed short)Caches[Cache1]->w - dx; x++)\r
+            {\r
+                if((x < (signed short)w) && (x >= 0))\r
+                {\r
+                    Data = *(unsigned long *)Buffer1;\r
+                    Buffer1 += 4;\r
+                    if(Data != 0)\r
+                    {\r
+                        if(*(unsigned long *)&Buffer2[(x + (y * w)) << 2] != 0)\r
+                            return(1);\r
+                    }\r
+                } else {\r
+                    Buffer1 += 4;\r
+                }\r
+            }\r
+        } else {\r
+            Buffer1 += Caches[Cache1]->w << 2;\r
+        }\r
+    }\r
+    return(0);\r
+}\r
+\r
+void __inline GetNextLineCoord(signed short *x, signed short *y, signed short *d, unsigned short dx, unsigned short dy, signed short xi, signed short yi)\r
+{\r
+    if(dx > dy)\r
+    {\r
+        *d += dy;\r
+        if(*d > dx)\r
+        {\r
+            *d -= dx;\r
+            *y += yi;\r
+        }\r
+        *x += xi;\r
+    } else {\r
+        *d += dx;\r
+        if(*d > 0)\r
+        {\r
+            *d -= dy;\r
+            *x += xi;\r
+        }\r
+        *y += yi;\r
+    }\r
+}\r
+\r
+unsigned short HitTest(signed short x, signed short y, unsigned short ObjNum, unsigned char TestCache, unsigned short TestFrame)\r
+{\r
+    unsigned short i;\r
+    unsigned short SpriteLink;\r
+    unsigned char Template;\r
+    signed short tx1, ty1, tx2, ty2;\r
+    unsigned long Offset;\r
+    unsigned char *FrameBuffer;\r
+\r
+    for(i = 0; i < MAX_HITTESTS; i++)\r
+    {\r
+        if(HitTests[i] == 0xFFFF)\r
+            break;\r
+        if(HitTests[i] == ObjNum)\r
+            continue;\r
+        SpriteLink = Objects[HitTests[i]]->SpriteLink;\r
+        if(SpriteLink != 0xFFFF)\r
+        {\r
+            Template = Sprites[SpriteLink]->Template;\r
+            if(TestCache == 0xFF)\r
+            {\r
+                tx1 = x;\r
+                ty1 = y;\r
+                tx2 = x;\r
+                ty2 = y;\r
+            } else {\r
+                tx1 = x - Caches[TestCache]->cx[TestFrame];\r
+                ty1 = y - Caches[TestCache]->cy[TestFrame];\r
+                tx2 = tx1 + Caches[TestCache]->w;\r
+                ty2 = ty1 + Caches[TestCache]->h;\r
+            }\r
+            if((tx2 >= Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame]) && (ty2 >= Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) && (tx1 < Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame] + Caches[Template]->w) && (ty1 < Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame] + Caches[Template]->h))\r
+            {\r
+                if(TestCache == 0xFF)\r
+                {\r
+                    Offset = x - Sprites[SpriteLink]->x + Caches[Template]->cx[Sprites[SpriteLink]->CurFrame];\r
+                    Offset += (y - Sprites[SpriteLink]->y + Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) * Caches[Template]->w;\r
+                    FrameBuffer = Caches[Template]->Frames[Sprites[SpriteLink]->CurFrame];\r
+                    if((Offset < Caches[Template]->w * Caches[Template]->h) && (*(unsigned long *)&FrameBuffer[Offset << 2] != 0))\r
+                        return(HitTests[i]);\r
+                } else {\r
+                    if(SpritesOverlap(TestCache, TestFrame, Template, Sprites[SpriteLink]->CurFrame, Sprites[SpriteLink]->x - x, Sprites[SpriteLink]->y - y) == 1)\r
+                        return(HitTests[i]);\r
+                }\r
+            }\r
+        }\r
+    }\r
+    return(0xFFFF);\r
+}\r
+\r
+unsigned char CollisionTest(signed short *x1, signed short *y1, signed short *x2, signed short *y2, unsigned char Pattern, unsigned char RunHitTests, unsigned short *ObjNum, unsigned char TestCache, unsigned short TestFrame)\r
+{\r
+    unsigned short i;\r
+    signed short dx, dy, x, y, fx, fy;\r
+    signed short xi, yi, d;\r
+    unsigned long Data;\r
+    unsigned char Collided;\r
+    unsigned short Object, ObjectList, NumObjects;\r
+\r
+    dx = *x2 - *x1;\r
+    dy = *y2 - *y1;\r
+    if(dx >= 0)\r
+    {\r
+        xi = 1;\r
+    } else {\r
+        xi = -1;\r
+        dx = -dx;\r
+    }\r
+    if(dy >= 0)\r
+    {\r
+        yi = 1;\r
+    } else {\r
+        yi = -1;\r
+        dy = -dy;\r
+    }\r
+    d = 0;\r
+    x = *x1;\r
+    y = *y1;\r
+    Collided = 0;\r
+    ObjectList = 0xFFFF;\r
+    if(dx > dy)\r
+    {\r
+        for(i = 0; i <= dx; i++)\r
+        {\r
+            fx = x;\r
+            fy = y;\r
+            d += dy;\r
+            if(d > dx)\r
+            {\r
+                d -= dx;\r
+                y += yi;\r
+            }\r
+            x += xi;\r
+            Data = GetMapPixel((unsigned short)x, (unsigned short)y, 1);\r
+            if((Data & Pattern) == 0)\r
+            {\r
+                *x1 = fx;\r
+                *y1 = fy;\r
+                *x2 = x;\r
+                *y2 = y;\r
+                if(Collided == 2)\r
+                    *ObjNum = ObjectList;\r
+                return(1 | Collided);\r
+            }\r
+            if(RunHitTests != 0)\r
+            {\r
+                if((Object = HitTest(x, y, *ObjNum, TestCache, TestFrame)) != 0xFFFF)\r
+                {\r
+                    if(RunHitTests == 1)\r
+                    {\r
+                        *x1 = fx;\r
+                        *y1 = fy;\r
+                        *x2 = x;\r
+                        *y2 = y;\r
+                        *ObjNum = Object;\r
+                        return(2);\r
+                    } else {\r
+                        if(ObjectList == 0xFFFF)\r
+                        {\r
+                            if((ObjectList = GetObjectList()) == 0xFFFF)\r
+                            {\r
+                                *x1 = fx;\r
+                                *y1 = fy;\r
+                                *x2 = x;\r
+                                *y2 = y;\r
+                                *ObjNum = 0xFFFF;\r
+                                return(2);\r
+                            }\r
+                        }\r
+                        NumObjects = ObjectLists[ObjectList]->NumObjects;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].Object = Object;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].x1 = fx;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].y1 = fy;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].x2 = x;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].y2 = y;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects + 1].Object = 0xFFFF;\r
+                        ObjectLists[ObjectList]->NumObjects++;\r
+                        Collided = 2;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    } else {\r
+        for(i = 0; i <= dy; i++)\r
+        {\r
+            fx = x;\r
+            fy = y;\r
+            d += dx;\r
+            if(d > 0)\r
+            {\r
+                d -= dy;\r
+                x += xi;\r
+            }\r
+            y += yi;\r
+            Data = GetMapPixel((unsigned short)x, (unsigned short)y, 1);\r
+            if((Data & Pattern) == 0)\r
+            {\r
+                *x1 = fx;\r
+                *y1 = fy;\r
+                *x2 = x;\r
+                *y2 = y;\r
+                if(Collided == 2)\r
+                    *ObjNum = ObjectList;\r
+                return(1 | Collided);\r
+            }\r
+            if(RunHitTests != 0)\r
+            {\r
+                if((Object = HitTest(x, y, *ObjNum, TestCache, TestFrame)) != 0xFFFF)\r
+                {\r
+                    if(RunHitTests == 1)\r
+                    {\r
+                        *x1 = fx;\r
+                        *y1 = fy;\r
+                        *x2 = x;\r
+                        *y2 = y;\r
+                        *ObjNum = Object;\r
+                        return(2);\r
+                    } else {\r
+                        if(ObjectList == 0xFFFF)\r
+                        {\r
+                            if((ObjectList = GetObjectList()) == 0xFFFF)\r
+                            {\r
+                                *x1 = fx;\r
+                                *y1 = fy;\r
+                                *x2 = x;\r
+                                *y2 = y;\r
+                                *ObjNum = 0xFFFF;\r
+                                return(2);\r
+                            }\r
+                        }\r
+                        NumObjects = ObjectLists[ObjectList]->NumObjects;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].Object = Object;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].x1 = fx;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].y1 = fy;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].x2 = x;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects].y2 = y;\r
+                        ObjectLists[ObjectList]->Objects[NumObjects + 1].Object = 0xFFFF;\r
+                        ObjectLists[ObjectList]->NumObjects++;\r
+                        Collided = 2;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+    return(Collided);\r
+}\r
+\r
+void AddHitTest(unsigned short ObjNum)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = 0; i < MAX_HITTESTS; i++)\r
+    {\r
+        if(HitTests[i] == 0xFFFF)\r
+        {\r
+            HitTests[i] = ObjNum;\r
+            return;\r
+        }\r
+    }\r
+}\r
+\r
+void RemoveHitTest(unsigned short ObjNum)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = 0; i < MAX_HITTESTS; i++)\r
+    {\r
+        if(HitTests[i] == ObjNum)\r
+        {\r
+            for(i = i; i < MAX_HITTESTS; i++)\r
+                HitTests[i] = HitTests[i + 1];\r
+            HitTests[MAX_HITTESTS - 1] = 0xFFFF;\r
+            break;\r
+        }\r
+    }\r
+}\r
+\r
+void FontPrint(unsigned char *Buffer, signed short sx, signed short y, unsigned short bgc)\r
+{\r
+    unsigned long Offset;\r
+    unsigned char CurChar;\r
+    unsigned short CharOffset;\r
+    signed short x;\r
+\r
+    Offset = 0;\r
+    x = sx;\r
+    while((CurChar = Buffer[Offset++]) != 0)\r
+    {\r
+        switch(CurChar)\r
+        {\r
+            case 10:\r
+                y += 6;\r
+                break;\r
+            case 13:\r
+                x = sx;\r
+                break;\r
+            default:\r
+                if(AsciiTable2[CurChar] != 255)\r
+                {\r
+                    if(bgc != 0)\r
+                        DBFRect(x, y, x + FontBuffer[(AsciiTable2[CurChar] << 1) + 1], y + 4, bgc);\r
+                    DBCopyBufferClip(x, y, (unsigned char *)&FontBuffer[FontBuffer[AsciiTable2[CurChar] << 1] + 512], FontBuffer[(AsciiTable2[CurChar] << 1) + 1], 5, 0);\r
+                } else {\r
+                    if(bgc != 0)\r
+                        DBFRect(x, y, x + 2, y + 4, bgc);\r
+                }\r
+                x += FontBuffer[(AsciiTable2[CurChar] << 1) + 1] + 1;\r
+                break;\r
+        }\r
+    }\r
+}\r
+\r
+void DBPrint(unsigned char *Buffer, signed short sx, signed short y, unsigned char bgc)\r
+{\r
+    unsigned long Offset;\r
+    unsigned char CurChar;\r
+    signed short x;\r
+\r
+    Offset = 0;\r
+    x = sx;\r
+    while((CurChar = Buffer[Offset++]) != 0)\r
+    {\r
+        switch(CurChar)\r
+        {\r
+            case 10:\r
+                y += 5;\r
+                break;\r
+            case 13:\r
+                x = sx;\r
+                break;\r
+            default:\r
+                if(AsciiTable[CurChar] != 65535)\r
+                {\r
+                    DBCopyBufferClip(x, y, Caches[FontSprite]->Frames[AsciiTable[CurChar]], Caches[FontSprite]->w, Caches[FontSprite]->h, bgc);\r
+                } else {\r
+                    if(bgc != 0)\r
+                        DBFRect(x, y, x + 2, y + 3, MakeColor(0, 0, 0));\r
+                }\r
+                x += Caches[FontSprite]->w + 1;\r
+                break;\r
+        }\r
+    }\r
+}\r
+\r
+unsigned short WallAngle(unsigned short x, unsigned short y)\r
+{\r
+   return(0);\r
+}\r
+\r
+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 long c)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = 0; i < MAX_PIXELS; i++)\r
+    {\r
+        if(Pixels[i]->Used == 0)\r
+        {\r
+            Pixels[i]->x = x;\r
+            Pixels[i]->y = y;\r
+            Pixels[i]->xv = xv;\r
+            Pixels[i]->yv = yv;\r
+            Pixels[i]->c = c;\r
+            Pixels[i]->SetColor = SetColor;\r
+            Pixels[i]->Explode = Explode;\r
+            Pixels[i]->Damage = Damage;\r
+            Pixels[i]->Owner = Owner;\r
+            Pixels[i]->Used = 1;\r
+            return;\r
+        }\r
+    }\r
+}\r
+\r
+void DrawLightning(signed short x1, signed short y1, signed short x2, signed short y2, signed short NumPoints, unsigned char Template)\r
+{\r
+    unsigned short i;\r
+    signed short x, y, fx, fy, nx, ny;\r
+    unsigned short Dist;\r
+    unsigned char Rad;\r
+\r
+    fx = x1;\r
+    fy = y1;\r
+    if(NumPoints <= 0)\r
+    {\r
+        while((Dist = (unsigned short)sqrt(((x2 - fx) * (x2 - fx)) + ((y2 - fy) * (y2 - fy)))) > 10)\r
+        {\r
+            nx = fx + (((x2 - fx) * 10) / Dist);\r
+            ny = fy + (((y2 - fy) * 10) / Dist);\r
+            Rad = -NumPoints;\r
+            while((GetMapPixel((x = nx + (signed short)(rand() % ((Rad * 2) + 1)) - Rad), (y = ny + (signed short)(rand() % ((Rad * 2) + 1)) - Rad), 1) & MAP_SHOOTABLE) == 0)\r
+                Rad++;\r
+            //DrawLine(fx, fy, x, y, 0, 0, 1, Template);\r
+            DrawLine(fx, fy, x, y, 0, 0, 1, Template);\r
+            fx = x;\r
+            fy = y;\r
+        }\r
+        DrawLine(fx, fy, x2, y2, 0, 0, 1, Template);\r
+    } else {\r
+        for(i = 0; i < NumPoints; i++)\r
+        {\r
+            x = x1 + (signed short)(((signed long)(x2 - x1) * (signed long)i) / (signed long)NumPoints);\r
+            y = y1 + (signed short)(((signed long)(y2 - y1) * (signed long)i) / (signed long)NumPoints);\r
+            x += (signed short)(rand() % 7) - 3;\r
+            y += (signed short)(rand() % 7) - 3;\r
+            DrawLine(fx, fy, x, y, 0, 0, 1, Template);\r
+            fx = x;\r
+            fy = y;\r
+        }\r
+    }\r
+}\r
+\r
+void DrawLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2, unsigned char Method, unsigned char UseSprite)\r
+{\r
+    static unsigned short i = 0;\r
+    unsigned short Start;\r
+\r
+    for(Start = i; i < MAX_LINES; i++)\r
+    {\r
+        if(Lines[i]->Used == 0)\r
+        {\r
+            Lines[i]->x1 = x1;\r
+            Lines[i]->y1 = y1;\r
+            Lines[i]->x2 = x2;\r
+            Lines[i]->y2 = y2;\r
+            Lines[i]->c1 = c1;\r
+            Lines[i]->c2 = c2;\r
+            Lines[i]->Transparent = Method;\r
+            Lines[i]->UseSprite = UseSprite;\r
+            Lines[i]->AnimTimer = 0;\r
+            Lines[i]->CurFrame = 0;\r
+            if(UseSprite == 0xFF)\r
+                Lines[i]->Used = 1;\r
+            else\r
+                Lines[i]->Used = Caches[UseSprite]->AnimDelay * Caches[UseSprite]->NumFrames;\r
+            return;\r
+        }\r
+    }\r
+    for(i = 0; i < Start; i++)\r
+    {\r
+        if(Lines[i]->Used == 0)\r
+        {\r
+            Lines[i]->x1 = x1;\r
+            Lines[i]->y1 = y1;\r
+            Lines[i]->x2 = x2;\r
+            Lines[i]->y2 = y2;\r
+            Lines[i]->c1 = c1;\r
+            Lines[i]->c2 = c2;\r
+            Lines[i]->Transparent = Method;\r
+            Lines[i]->UseSprite = UseSprite;\r
+            Lines[i]->AnimTimer = 0;\r
+            Lines[i]->CurFrame = 0;\r
+            if(UseSprite == 0xFF)\r
+                Lines[i]->Used = 1;\r
+            else\r
+                Lines[i]->Used = Caches[UseSprite]->AnimDelay * Caches[UseSprite]->NumFrames;\r
+            return;\r
+        }\r
+    }\r
+}\r
+\r
+void DrawCircle(signed short x, signed short y, unsigned short r, unsigned long Color, unsigned char Transparent)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = 0; i < MAX_RASTERS; i++)\r
+    {\r
+        if(Rasters[i]->Used == 0)\r
+        {\r
+            Rasters[i]->x1 = x;\r
+            Rasters[i]->y1 = y;\r
+            Rasters[i]->x2 = r;\r
+            Rasters[i]->Color = Color;\r
+            Rasters[i]->Transparent = Transparent;\r
+            Rasters[i]->Type = 1;\r
+            Rasters[i]->Used = 1;\r
+            return;\r
+        }\r
+    }\r
+}\r
+\r
+void DrawPoly(signed short x1, signed short y1, signed short x2, signed short y2, signed short x3, signed short y3, unsigned long Color, unsigned char Transparent)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = 0; i < MAX_RASTERS; i++)\r
+    {\r
+        if(Rasters[i]->Used == 0)\r
+        {\r
+            Rasters[i]->x1 = x1;\r
+            Rasters[i]->y1 = y1;\r
+            Rasters[i]->x2 = x2;\r
+            Rasters[i]->y2 = y2;\r
+            Rasters[i]->x3 = x3;\r
+            Rasters[i]->y3 = y3;\r
+            Rasters[i]->Color = Color;\r
+            Rasters[i]->Transparent = Transparent;\r
+            Rasters[i]->Type = 0;\r
+            Rasters[i]->Used = 1;\r
+            return;\r
+        }\r
+    }\r
+}\r
+\r
+unsigned short SpawnObject(unsigned short Class, unsigned char Owner, unsigned short x, unsigned short y, float xv, float yv)\r
+{\r
+    static unsigned short i = 0;\r
+    unsigned short Start;\r
+\r
+    for(Start = i; i < MAX_OBJECTS; i++)\r
+    {\r
+        if(Objects[i]->Used == 0)\r
+        {\r
+            Objects[i]->x = (float)x;\r
+            Objects[i]->y = (float)y;\r
+            Objects[i]->xv = xv;\r
+            Objects[i]->yv = yv;\r
+            Objects[i]->Class = Class;\r
+            Objects[i]->Owner = Owner;\r
+            Objects[i]->TickTimer = 0;\r
+            Objects[i]->TouchTimer = Classes[Class]->TouchDelay;\r
+            Objects[i]->SpriteLink = (Classes[Class]->Sprite != 0xFF)?(SpawnSprite(Classes[Class]->Sprite, (signed short)x, (signed short)y, 0, 0, 0, Classes[Class]->StartFrame, Classes[Class]->TransSprite)):0xFFFF;\r
+            Objects[i]->Used = 1;\r
+            Regs[16] = i;\r
+            Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[2]);                        //Init\r
+            return(i);\r
+        }\r
+    }\r
+    for(i = 0; i < Start; i++)\r
+    {\r
+        if(Objects[i]->Used == 0)\r
+        {\r
+            Objects[i]->x = (float)x;\r
+            Objects[i]->y = (float)y;\r
+            Objects[i]->xv = xv;\r
+            Objects[i]->yv = yv;\r
+            Objects[i]->Class = Class;\r
+            Objects[i]->Owner = Owner;\r
+            Objects[i]->TickTimer = 0;\r
+            Objects[i]->TouchTimer = Classes[Class]->TouchDelay;\r
+            Objects[i]->SpriteLink = (Classes[Class]->Sprite != 0xFF)?(SpawnSprite(Classes[Class]->Sprite, (signed short)x, (signed short)y, 0, 0, 0, Classes[Class]->StartFrame, Classes[Class]->TransSprite)):0xFFFF;\r
+            Objects[i]->Used = 1;\r
+            Regs[16] = i;\r
+            Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[2]);                        //Init\r
+            return(i);\r
+        }\r
+    }\r
+    return(0xFFFF);\r
+}\r
+\r
+unsigned short GetObjectList(void)\r
+{\r
+    unsigned char i;\r
+\r
+    for(i = 0; i < MAX_OBJLISTS; i++)\r
+    {\r
+        if(ObjectLists[i]->Used == 0)\r
+        {\r
+            ObjectLists[i]->Objects[0].Object = 0xFFFF;\r
+            ObjectLists[i]->NumObjects = 0;\r
+            ObjectLists[i]->Used = 1;\r
+            return(i);\r
+        }\r
+    }\r
+    return(0xFFFF);\r
+}\r
+\r
+void ControlObjects(void)\r
+{\r
+    unsigned short i, o;\r
+    unsigned short Class;\r
+    signed short fx, fy, nx, ny, dx, dy, x, y;\r
+    signed short x1, y1, x2, y2, tx1, ty1, tx2, ty2;\r
+    unsigned char PixelInfo, Collided, Template;\r
+    unsigned short ObjNum, SpriteLink, TestFrame;\r
+    unsigned char *FrameBuffer;\r
+\r
+    for(i = 0; i < MAX_OBJECTS; i++)\r
+    {\r
+        if(Objects[i]->Used == 2)\r
+            Objects[i]->Used = 0;\r
+    }\r
+    for(i = 0; i < MAX_OBJECTS; i++)\r
+    {\r
+        if(Objects[i]->Used == 1)\r
+        {\r
+            Class = Objects[i]->Class;\r
+            fx = (signed short)Objects[i]->x;\r
+            fy = (signed short)Objects[i]->y;\r
+            Objects[i]->yv += Gravity * ((float)Classes[Class]->GravityMod / 10000);\r
+            Objects[i]->x += Objects[i]->xv;\r
+            Objects[i]->y += Objects[i]->yv;\r
+            if(Objects[i]->TouchTimer > 0)\r
+                Objects[i]->TouchTimer--;\r
+            nx = (signed short)Objects[i]->x;\r
+            ny = (signed short)Objects[i]->y;\r
+            dx = nx - fx;\r
+            dy = ny - fy;\r
+            if(dx < 0)\r
+                dx = -dx;\r
+            if(dy < 0)\r
+                dy = -dy;\r
+            if((dx > 1) || (dy > 1))\r
+            {\r
+                ObjNum = i;\r
+                SpriteLink = Objects[i]->SpriteLink;\r
+                if(SpriteLink != 0xFFFF)\r
+                    Template = Sprites[SpriteLink]->Template;\r
+                else\r
+                    Template = 0xFF;\r
+                Collided = CollisionTest((signed short *)&fx, (signed short *)&fy, (signed short *)&nx, (signed short *)&ny, MAP_SHOOTABLE, Classes[Class]->RunHitTests, (unsigned short *)&ObjNum, Template, (Template == 0xFF)?0:Sprites[SpriteLink]->CurFrame);\r
+            } else {\r
+                Collided = (GetMapPixel((unsigned short)nx, (unsigned short)ny, 1) & MAP_SHOOTABLE) == 0;\r
+                if(Classes[Class]->RunHitTests == 1)\r
+                {\r
+                    x = nx;\r
+                    y = ny;\r
+                    if((SpriteLink = Objects[i]->SpriteLink) == 0xFFFF)\r
+                    {\r
+                        Template = 0xFF;\r
+                    } else {\r
+                        Template = Sprites[SpriteLink]->Template;\r
+                        TestFrame = Sprites[SpriteLink]->CurFrame;\r
+                    }\r
+                    if((ObjNum = HitTest(x, y, i, Template, TestFrame)) != 0xFFFF)\r
+                        Collided = 2;\r
+                    /*for(o = 0; o < MAX_HITTESTS; o++)\r
+                    {\r
+                        if(HitTests[o] == 0xFFFF)\r
+                            break;\r
+                        if(HitTests[o] == i)\r
+                            continue;\r
+                        SpriteLink = Objects[HitTests[o]]->SpriteLink;\r
+                        if(SpriteLink != 0xFFFF)\r
+                        {\r
+                            if(SpriteLink != 0xFFFF)\r
+                                Template = Sprites[SpriteLink]->Template;\r
+                            else\r
+                                Template = 0xFF;\r
+                            if(Objects[i]->SpriteLink != 0xFFFF)\r
+                            {\r
+                                SpriteLink2 = Objects[i]->SpriteLink;\r
+                                TestFrame = Sprites[SpriteLink2]->CurFrame;\r
+                                Template2 = Sprites[SpriteLink2]->Template;\r
+                            } else {\r
+                                SpriteLink2 = 0xFFFF;\r
+                                TestFrame = 0;\r
+                                Template2 = 0xFF;\r
+                            }\r
+                            if(Template2 == 0xFF)\r
+                            {\r
+                                tx1 = x;\r
+                                ty1 = y;\r
+                                tx2 = x;\r
+                                ty2 = y;\r
+                            } else {\r
+                                tx1 = x - Caches[Template2]->cx[TestFrame];\r
+                                ty1 = y - Caches[Template2]->cy[TestFrame];\r
+                                tx2 = x - Caches[Template2]->cx[TestFrame] + Caches[Template2]->w;\r
+                                ty2 = y - Caches[Template2]->cy[TestFrame] + Caches[Template2]->h;\r
+                            }\r
+                            if((tx2 >= Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame]) && (ty2 >= Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) && (tx1 < Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame] + Caches[Template]->w) && (ty1 < Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame] + Caches[Template]->h))\r
+                            {\r
+                                if(Objects[i]->SpriteLink == 0xFFFF)\r
+                                {\r
+                                    Offset = x - Sprites[SpriteLink]->x + Caches[Template]->cx[Sprites[SpriteLink]->CurFrame];\r
+                                    Offset += (y - Sprites[SpriteLink]->y + Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) * Caches[Template]->w;\r
+                                    FrameBuffer = Caches[Template]->Frames[Sprites[SpriteLink]->CurFrame];\r
+                                    if((Offset < Caches[Template]->w * Caches[Template]->h) && (*(unsigned long *)&FrameBuffer[Offset << 2] != 0))\r
+                                    {\r
+                                        ObjNum = HitTests[o];\r
+                                        Collided = 2;\r
+                                        break;\r
+                                    }\r
+                                } else {\r
+                                    if(SpritesOverlap(Template2, TestFrame, Template, Sprites[SpriteLink]->CurFrame, Sprites[SpriteLink]->x - x, Sprites[SpriteLink]->y - y))\r
+                                    {\r
+                                        ObjNum = HitTests[o];\r
+                                        Collided = 2;\r
+                                        break;\r
+                                    }\r
+                                }\r
+                            }\r
+                        }\r
+                    }*/\r
+                }\r
+            }\r
+            if(Collided != 0)\r
+            {\r
+                if((Collided == 2)?((Objects[i]->Owner != 0xFF)?((ObjNum == Players[Objects[i]->Owner]->Object)?(Objects[i]->TouchTimer == 0):1):1):1)\r
+                {\r
+                    PixelInfo = GetMapPixel((unsigned short)nx, (unsigned short)ny, 1);\r
+                    Regs[16] = i;\r
+                    Regs[17] = fx;\r
+                    Regs[18] = fy;\r
+                    Regs[19] = ((PixelInfo & MAP_SHOOTABLE) == 0)?0:1;\r
+                    Regs[20] = ((PixelInfo & MAP_WALKABLE) == 0)?0:1;\r
+                    Regs[21] = ((PixelInfo & MAP_DESTROYABLE) == 0)?0:1;\r
+                    Regs[22] = nx;\r
+                    Regs[23] = ny;\r
+                    Regs[24] = Collided;\r
+                    Regs[25] = ObjNum;\r
+                    Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[1]);                    //Touch\r
+                }\r
+            }\r
+            if((Classes[Class]->TickDelay != 0) && (Objects[i]->Used == 1))\r
+            {\r
+                if(++Objects[i]->TickTimer >= Classes[Class]->TickDelay)\r
+                {\r
+                    PixelInfo = GetMapPixel((unsigned short)Objects[i]->x, (unsigned short)Objects[i]->y, 1);\r
+                    Objects[i]->TickTimer = 0;\r
+                    Regs[16] = i;\r
+                    Regs[17] = (signed short)Objects[i]->x;\r
+                    Regs[18] = (signed short)Objects[i]->y;\r
+                    Regs[19] = ((PixelInfo & MAP_SHOOTABLE) == 0)?0:1;\r
+                    Regs[20] = ((PixelInfo & MAP_WALKABLE) == 0)?0:1;\r
+                    Regs[21] = ((PixelInfo & MAP_DESTROYABLE) == 0)?0:1;\r
+                    Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[0]);                    //Tick\r
+                }\r
+            }\r
+            if(Objects[i]->SpriteLink != 0xFFFF)\r
+            {\r
+                Sprites[Objects[i]->SpriteLink]->x = (signed short)Objects[i]->x;\r
+                Sprites[Objects[i]->SpriteLink]->y = (signed short)Objects[i]->y;\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void ControlSprites(void)\r
+{\r
+    unsigned short i;\r
+    unsigned char Template;\r
+\r
+    for(i = 0; i < MAX_SPRITES; i++)\r
+    {\r
+        if(Sprites[i]->Used == 1)\r
+        {\r
+            Template = Sprites[i]->Template;\r
+            Sprites[i]->x += Sprites[i]->xv;\r
+            Sprites[i]->y += Sprites[i]->yv;\r
+            if(Sprites[i]->AnimDelay != 0xFF)\r
+            {\r
+                if(++Sprites[i]->AnimTimer >= Sprites[i]->AnimDelay)\r
+                {\r
+                    Sprites[i]->AnimTimer = 0;\r
+                    if(++Sprites[i]->CurFrame >= Caches[Template]->NumFrames)\r
+                    {\r
+                        Sprites[i]->CurFrame = 0;\r
+                        if(Sprites[i]->AnimCount > 0)\r
+                        {\r
+                            if(--Sprites[i]->AnimCount == 0)\r
+                            {\r
+                                Sprites[i]->Used = 0;\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_LINES; i++)\r
+    {\r
+        if(Lines[i]->Used > 0)\r
+        {\r
+            Lines[i]->Used--;\r
+            if((Lines[i]->UseSprite != 0xFF) && (Caches[Lines[i]->UseSprite]->AnimDelay != 0xFF))\r
+            {\r
+                if(++Lines[i]->AnimTimer >= Caches[Lines[i]->UseSprite]->AnimDelay)\r
+                {\r
+                    Lines[i]->AnimTimer = 0;\r
+                    if(++Lines[i]->CurFrame >= Caches[Lines[i]->UseSprite]->NumFrames)\r
+                        Lines[i]->CurFrame = 0;\r
+                }\r
+            }\r
+        }\r
+    }\r
+    for(i = 0; i < MAX_RASTERS; i++)\r
+        Rasters[i]->Used = 0;\r
+}\r
+\r
+void ControlPixels(void)\r
+{\r
+    unsigned short i, o;\r
+    signed short fx, fy, nx, ny, dx, dy, x, y;\r
+    unsigned char Collided;\r
+    unsigned short ObjNum, SpriteLink, Template, Offset;\r
+    unsigned char *FrameBuffer;\r
+\r
+    for(i = 0; i < MAX_PIXELS; i++)\r
+    {\r
+        if(Pixels[i]->Used == 1)\r
+        {\r
+            fx = (signed short)Pixels[i]->x;\r
+            fy = (signed short)Pixels[i]->y;\r
+            Pixels[i]->x += Pixels[i]->xv;\r
+            Pixels[i]->y += Pixels[i]->yv;\r
+            nx = (signed short)Pixels[i]->x;\r
+            ny = (signed short)Pixels[i]->y;\r
+            dx = nx - fx;\r
+            dy = ny - fy;\r
+            if(dx < 0)\r
+                dx = -dx;\r
+            if(dy < 0)\r
+                dy = -dy;\r
+            if((dx > 1) || (dy > 1))\r
+            {\r
+                ObjNum = 0xFFFF;\r
+                Collided = CollisionTest((signed short *)&fx, (signed short *)&fy, (signed short *)&nx, (signed short *)&ny, MAP_SHOOTABLE, Pixels[i]->Explode, (unsigned short *)&ObjNum, 0xFF, 0);\r
+            } else {\r
+                Collided = (GetMapPixel((unsigned short)Pixels[i]->x, (unsigned short)Pixels[i]->y, 1) & MAP_SHOOTABLE) == 0;\r
+                if(Pixels[i]->Explode == 1)\r
+                {\r
+                    x = (signed short)Pixels[i]->x;\r
+                    y = (signed short)Pixels[i]->y;\r
+                    if((ObjNum = HitTest(x, y, 0xFFFF, 0xFF, 0)) != 0xFFFF)\r
+                    {\r
+                        Collided = 2;\r
+                    }\r
+                }\r
+            }\r
+            Pixels[i]->yv += Gravity;\r
+            if(Collided != 0)\r
+            {\r
+                if(Pixels[i]->SetColor == 1)\r
+                {\r
+                    SetMapPixel((unsigned short)nx, (unsigned short)ny, Pixels[i]->c, 0);\r
+                }\r
+                if(Pixels[i]->SetColor == 2)\r
+                {\r
+                    if((GetMapPixel((unsigned short)fx, (unsigned short)fy, 1) & MAP_SHOOTABLE) == MAP_SHOOTABLE)\r
+                    {\r
+                        SetMapPixel((unsigned short)fx, (unsigned short)fy, Pixels[i]->c, 0);\r
+                        SetMapPixel((unsigned short)fx, (unsigned short)fy, MAP_DESTROYABLE, 1);\r
+                    }\r
+                }\r
+                if(Pixels[i]->Explode == 1)\r
+                {\r
+                    if(Collided == 1)\r
+                        SpawnExplosion((signed short)nx, (signed short)ny, 7, 0, 1);\r
+                    if(Collided == 2)\r
+                    {\r
+                        Objects[ObjNum]->xv += Pixels[i]->xv * (float)Pixels[i]->Damage * 0.013;\r
+                        Objects[ObjNum]->yv += Pixels[i]->yv * (float)Pixels[i]->Damage * 0.013;\r
+                        Regs[16] = (signed short)ObjNum;\r
+                        Regs[17] = Pixels[i]->Damage;\r
+                        Regs[18] = (signed short)Pixels[i]->Owner;\r
+                        Regs[19] = (signed short)Objects[ObjNum]->x;\r
+                        Regs[20] = (signed short)Objects[ObjNum]->y;\r
+                        Execute(Classes[Objects[ObjNum]->Class]->Code, (signed short *)&Objects[ObjNum]->Variables[0], Classes[Objects[ObjNum]->Class]->Scripts[3]);                        //TakeDamage\r
+                    }\r
+                }\r
+                Pixels[i]->Used = 0;\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void CollVel(signed short x, signed short y, float *xv, float *yv, unsigned char Attributes)\r
+{\r
+    float Temp;\r
+    signed char xa, ya;\r
+    unsigned char a1, a2;\r
+\r
+    if(*xv < 0)\r
+        xa = -1;\r
+    else\r
+        xa = 1;\r
+    if(*yv < 0)\r
+        ya = -1;\r
+    else\r
+        ya = 1;\r
+    a1 = GetMapPixel(x, y + ya, 1) & Attributes;\r
+    a2 = GetMapPixel(x + xa, y, 1) & Attributes;\r
+    if(((a1 == 0) && (a2 == 0)) || ((a1 != 0) && (a2 != 0)))\r
+    {\r
+        Temp = *yv;\r
+        *yv = *xv * (float)(xa * -ya);\r
+        *xv = Temp * (float)(ya * -xa);\r
+    } else {\r
+        if(a1 == 0)\r
+            *yv = -*yv;\r
+        if(a2 == 0)\r
+            *xv = -*xv;\r
+    }\r
+}\r
+\r
+void ControlPlayers(void)\r
+{\r
+    unsigned short i, o;\r
+    unsigned short ObjNum;\r
+    signed short PlayerAngle, CurWeapon;\r
+\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        if(Players[i]->Used == 1)\r
+        {\r
+            ObjNum = Players[i]->Object;\r
+            PlayerAngle = Players[i]->Angle;\r
+            if(PlayerAngle > 90)\r
+                PlayerAngle -= 360;\r
+            if(Players[i]->Dir == 1)\r
+                PlayerAngle = 180 - PlayerAngle;\r
+            if(PlayerAngle < 0)\r
+                PlayerAngle += 360;\r
+            for(o = 0; o < NUM_WEAPONS; o++)\r
+            {\r
+                if(PWeapons[i][o]->Used == 1)\r
+                {\r
+                    if(PWeapons[i][o]->FireTimer > 0)\r
+                    {\r
+                        if(++PWeapons[i][o]->FireTimer > Weapons[PWeapons[i][o]->Weapon]->FireDelay)\r
+                            PWeapons[i][o]->FireTimer = 0;\r
+                    }\r
+                    if((PWeapons[i][o]->ReloadTimer > 0) && (Players[i]->CurWeapon == o))\r
+                    {\r
+                        if((Weapons[PWeapons[i][o]->Weapon]->MaxClips > 0) && (PWeapons[i][o]->NumClips == 0))\r
+                        {\r
+                            PWeapons[i][o]->ReloadTimer = 0;\r
+                        } else {\r
+                            if(++PWeapons[i][o]->ReloadTimer > Weapons[PWeapons[i][o]->Weapon]->ReloadDelay)\r
+                            {\r
+                                PWeapons[i][o]->ReloadTimer = 0;\r
+                                PWeapons[i][o]->AmmoLeft = Weapons[PWeapons[i][o]->Weapon]->Ammo;\r
+                                PlaySound(2, 0, 0, MAX_SOUNDS - 1, 22050, 1);\r
+                            }\r
+                        }\r
+                    }\r
+                    Regs[16] = (signed short)ObjNum;\r
+                    if(Players[i]->Dir == 0)\r
+                    {\r
+                        Regs[17] = (signed short)Objects[ObjNum]->x + 3 + Cosine[PlayerAngle] * 7;\r
+                    } else {\r
+                        Regs[17] = (signed short)Objects[ObjNum]->x - 1 + Cosine[PlayerAngle] * 7;\r
+                    }\r
+                    Regs[18] = (signed short)Objects[ObjNum]->y - 2 - Sine[PlayerAngle] * 7;\r
+                    Regs[19] = (signed short)PlayerAngle;\r
+                    Regs[20] = (signed short)i;\r
+                    Regs[21] = (signed short)o;\r
+                    Execute(Classes[Weapons[PWeapons[i][o]->Weapon]->Class]->Code, (signed short *)&PWeapons[i][o]->Vars[0], Classes[Weapons[PWeapons[i][o]->Weapon]->Class]->Scripts[1]);                                                      //Tick\r
+                }\r
+            }\r
+            Players[i]->Angle += Players[i]->AngleVel;\r
+            if((signed short)Players[i]->Angle >= 360)\r
+                Players[i]->Angle -= 360;\r
+            if((signed short)Players[i]->Angle < 0)\r
+                Players[i]->Angle += 360;\r
+            if((Players[i]->Angle < 300) && (Players[i]->Angle > 180))\r
+            {\r
+                Players[i]->Angle = 300;\r
+                Players[i]->AngleVel = 0;\r
+            }\r
+            if((Players[i]->Angle > 90) && (Players[i]->Angle <= 180))\r
+            {\r
+                Players[i]->Angle = 90;\r
+                Players[i]->AngleVel = 0;\r
+            }\r
+            if(((Players[i]->Left != 0) ^ (Players[i]->Right != 0)) & (Players[i]->Change == 0))\r
+            {\r
+                if(Players[i]->Left != 0)\r
+                {\r
+                    if(((GetMapPixel((unsigned short)(Objects[ObjNum]->x) - 1, (unsigned short)(Objects[ObjNum]->y) - 1, 1) & MAP_WALKABLE) == MAP_WALKABLE) && (Objects[ObjNum]->xv > -1))\r
+                        Objects[ObjNum]->xv -= 0.1;\r
+                    Players[i]->Dir = 1;\r
+                }\r
+                if(Players[i]->Right != 0)\r
+                {\r
+                    if(((GetMapPixel((unsigned short)(Objects[ObjNum]->x) + 1, (unsigned short)(Objects[ObjNum]->y) - 1, 1) & MAP_WALKABLE) == MAP_WALKABLE) && (Objects[ObjNum]->xv < 1))\r
+                        Objects[ObjNum]->xv += 0.1;\r
+                    Players[i]->Dir = 0;\r
+                }\r
+            } else {\r
+                if((GetMapPixel((unsigned short)Objects[ObjNum]->x, (unsigned short)Objects[ObjNum]->y, 1) & MAP_WALKABLE) == 0)\r
+                    Objects[ObjNum]->xv *= 0.9;\r
+            }\r
+            if((Players[i]->Change != 0) && (Players[i]->Left == 1))\r
+            {\r
+                Players[i]->CurWeapon -= 1;\r
+                if(Players[i]->CurWeapon < 0)\r
+                    Players[i]->CurWeapon += NUM_WEAPONS;\r
+                while(PWeapons[i][Players[i]->CurWeapon]->Used == 0)\r
+                {\r
+                    Players[i]->CurWeapon -= 1;\r
+                    if(Players[i]->CurWeapon < 0)\r
+                        Players[i]->CurWeapon += NUM_WEAPONS;\r
+                }\r
+            }\r
+            if((Players[i]->Change != 0) && (Players[i]->Right == 1))\r
+            {\r
+                Players[i]->CurWeapon += 1;\r
+                if(Players[i]->CurWeapon >= NUM_WEAPONS)\r
+                    Players[i]->CurWeapon -= NUM_WEAPONS;\r
+                while(PWeapons[i][Players[i]->CurWeapon]->Used == 0)\r
+                {\r
+                    Players[i]->CurWeapon += 1;\r
+                    if(Players[i]->CurWeapon >= NUM_WEAPONS)\r
+                        Players[i]->CurWeapon -= NUM_WEAPONS;\r
+                }\r
+            }\r
+            if((Players[i]->Up != 0) ^ (Players[i]->Down != 0))\r
+            {\r
+                if((Players[i]->Up != 0) && (Players[i]->AngleVel < 3))\r
+                    Players[i]->AngleVel += .5;\r
+                if((Players[i]->Down != 0) && (Players[i]->AngleVel > -3))\r
+                    Players[i]->AngleVel -= .5;\r
+            } else {\r
+                Players[i]->AngleVel *= .75;\r
+            }\r
+            PlayerAngle = Players[i]->Angle;\r
+            if(PlayerAngle > 90)\r
+                PlayerAngle -= 360;\r
+            if(Players[i]->Dir == 1)\r
+                PlayerAngle = 180 - PlayerAngle;\r
+            if(PlayerAngle < 0)\r
+                PlayerAngle += 360;\r
+            CurWeapon = Players[i]->CurWeapon;\r
+            Players[i]->JustShot = 0;\r
+            if((Players[i]->Shoot != 0) && (PWeapons[i][CurWeapon]->FireTimer == 0) && (PWeapons[i][CurWeapon]->ReloadTimer == 0) && ((Weapons[PWeapons[i][CurWeapon]->Weapon]->MaxClips > 0)?(PWeapons[i][CurWeapon]->NumClips > 0):1))\r
+            {\r
+                PWeapons[i][Players[i]->CurWeapon]->FireTimer = 1;\r
+                if(Players[i]->Dir == 0)\r
+                {\r
+                    Regs[16] = (signed short)Objects[ObjNum]->x + 3 + Cosine[PlayerAngle] * 7;\r
+                } else {\r
+                    Regs[16] = (signed short)Objects[ObjNum]->x - 1 + Cosine[PlayerAngle] * 7;\r
+                }\r
+                Regs[17] = (signed short)Objects[ObjNum]->y - 2 - Sine[PlayerAngle] * 7;\r
+                Regs[18] = (signed short)PlayerAngle;\r
+                Regs[19] = (signed short)(Objects[ObjNum]->xv * 100);\r
+                Regs[20] = (signed short)(Objects[ObjNum]->yv * 100);\r
+                Regs[21] = (signed short)i;\r
+                if(Weapons[PWeapons[i][CurWeapon]->Weapon]->MaxClips > 0)\r
+                    PWeapons[i][CurWeapon]->NumClips--;\r
+                Execute(Classes[Weapons[PWeapons[i][CurWeapon]->Weapon]->Class]->Code, (signed short *)&PWeapons[i][CurWeapon]->Vars[0], Classes[Weapons[PWeapons[i][CurWeapon]->Weapon]->Class]->Scripts[0]);                                                  //Fire\r
+                if(--PWeapons[i][CurWeapon]->AmmoLeft <= 0)\r
+                    PWeapons[i][CurWeapon]->ReloadTimer = 1;\r
+                Players[i]->JustShot = 1;\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void SaveBitmap(unsigned char *Buffer, unsigned short w, unsigned short h, unsigned char *FileName)\r
+{\r
+    KvidFile BMPFile;\r
+    unsigned long LongBuffer;\r
+    unsigned short x, y;\r
+\r
+    if((CreateFile(FileName, &BMPFile, NULL, 0) == 0) || (BMPFile.CanWrite == 0))\r
+        return;\r
+    FileWrite((void *)"BM", 2, &BMPFile);\r
+    LongBuffer = 54 + (w * h * 3) + ((w % 4) * h);\r
+    FileWrite((void *)&LongBuffer, 4, &BMPFile);\r
+    FileWrite((void *)"\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00", 12, &BMPFile);\r
+    LongBuffer = w;\r
+    FileWrite((void *)&LongBuffer, 4, &BMPFile);\r
+    LongBuffer = h;\r
+    FileWrite((void *)&LongBuffer, 4, &BMPFile);\r
+    FileWrite((void *)"\x01\x00\x18\x00\x00\x00\x00\x00", 8, &BMPFile);\r
+    LongBuffer = (w * h * 3) + ((w % 4) * h);\r
+    FileWrite((void *)&LongBuffer, 4, &BMPFile);\r
+    FileWrite((void *)"\xC4\x0E\x00\x00\xC4\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, &BMPFile);\r
+    LongBuffer = 0;\r
+    for(y = 0; y < h; y++)\r
+    {\r
+        for(x = 0; x < w; x++)\r
+        {\r
+            FileWrite((void *)(Buffer + (x << 2) + ((h - y - 1) * 1280)), 3, &BMPFile);\r
+        }\r
+        FileWrite((void *)&LongBuffer, w % 4, &BMPFile);\r
+    }\r
+    FileClose(&BMPFile);\r
+}\r
+\r
+void ControlMasks(void)\r
+{\r
+    unsigned short i, o, u;\r
+    unsigned short x, y, w, h;\r
+    unsigned short R, G, B;\r
+    unsigned char Colors;\r
+    unsigned char *Buffer;\r
+    Color c;\r
+\r
+    for(i = 0; i < MAX_PLAYERS; i++)\r
+    {\r
+        if(Players[i]->Used == 1)\r
+        {\r
+            w = Players[i]->VPointX2 - Players[i]->VPointX1 + 1;\r
+            h = Players[i]->VPointY2 - Players[i]->VPointY1 + 1;\r
+            for(o = 0; o < NUM_MASKS; o++)\r
+            {\r
+                Buffer = Players[i]->Masks[o].Buffer;\r
+                for(u = 0; u < 16; u++)\r
+                {\r
+                    if(Players[i]->Masks[o].Effects[u] == 0)\r
+                        break;\r
+                    switch(Players[i]->Masks[o].Effects[u])\r
+                    {\r
+                        case 1:\r
+                            for(y = 0; y < h; y++)\r
+                            {\r
+                                for(x = 0; x < w; x++)\r
+                                {\r
+                                    *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + x) << 2));\r
+                                    R = c.R; G = c.G; B = c.B;\r
+                                    Colors = 1;\r
+                                    if(x > 0)\r
+                                    {\r
+                                        *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + (x - 1)) << 2));\r
+                                        R += c.R; G += c.G; B += c.B;\r
+                                        Colors++;\r
+                                    }\r
+                                    if(x < w - 1)\r
+                                    {\r
+                                        *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + (x + 1)) << 2));\r
+                                        R += c.R; G += c.G; B += c.B;\r
+                                        Colors++;\r
+                                    }\r
+                                    if(y > 0)\r
+                                    {\r
+                                        *(unsigned long *)&c = *(unsigned long *)(Buffer + (((y - 1) * w + x) << 2));\r
+                                        R += c.R; G += c.G; B += c.B;\r
+                                        Colors++;\r
+                                    }\r
+                                    if(y < h - 1)\r
+                                    {\r
+                                        *(unsigned long *)&c = *(unsigned long *)(Buffer + (((y + 1) * w + x) << 2));\r
+                                        R += c.R; G += c.G; B += c.B;\r
+                                        Colors++;\r
+                                    }\r
+                                    *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + x) << 2));\r
+                                    R /= Colors;\r
+                                    G /= Colors;\r
+                                    B /= Colors;\r
+                                    if(R > c.R || G > c.G || B > c.B)\r
+                                    {\r
+                                        c.R = R;\r
+                                        c.G = G;\r
+                                        c.B = B;\r
+                                    }\r
+                                    if(c.R > 0)\r
+                                        c.R--;\r
+                                    if(c.G > 0)\r
+                                        c.G--;\r
+                                    if(c.B > 0)\r
+                                        c.B--;\r
+                                    *(unsigned long *)(Buffer + ((y * w + x) << 2)) = *(unsigned long *)&c;\r
+                                }\r
+                            }\r
+                            break;\r
+                        case 2:\r
+                            for(y = 0; y < h; y++)\r
+                            {\r
+                                for(x = 0; x < w; x++)\r
+                                {\r
+                                    *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + x) << 2));\r
+                                    c.R /= 2;\r
+                                    c.G /= 2;\r
+                                    c.B /= 2;\r
+                                    *(unsigned long *)(Buffer + ((y * w + x) << 2)) = *(unsigned long *)&c;\r
+                                }\r
+                            }\r
+                            break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+unsigned char ControlMenu(unsigned char Key)\r
+{\r
+    unsigned short i, o, x, y, Signature, l;\r
+    KvidFile ModFile;\r
+    unsigned char ValidLevel;\r
+    DIR *d;\r
+    struct dirent *de;\r
+\r
+    //DBFRectTrans(100, 30, 220, 150, MakeColor(0, 64, 0), 2);\r
+    DBLine(100, 30, 100, 150, MakeColor(0, 150, 0), MakeColor(0, 150, 0));\r
+    DBLine(100, 30, 220, 30, MakeColor(0, 150, 0), MakeColor(0, 150, 0));\r
+    DBLine(220, 30, 220, 150, MakeColor(0, 150, 0), MakeColor(0, 150, 0));\r
+    DBLine(100, 150, 220, 150, MakeColor(0, 150, 0), MakeColor(0, 150, 0));\r
+    DBLineTrans(101, 31, 101, 149, MakeColor(0, 150, 0), MakeColor(0, 150, 0), 2);\r
+    DBLineTrans(101, 31, 219, 31, MakeColor(0, 150, 0), MakeColor(0, 150, 0), 2);\r
+    DBLineTrans(219, 31, 219, 149, MakeColor(0, 150, 0), MakeColor(0, 150, 0), 2);\r
+    DBLineTrans(101, 149, 219, 149, MakeColor(0, 150, 0), MakeColor(0, 150, 0), 2);\r
+    DBFRectTrans(102, 32, 218, 148, MakeColor(0, 64, 0), 2);\r
+    if((Key == 200) && (CurMenuItem > 0))\r
+        CurMenuItem--;\r
+    if((Key == 208) && (CurMenuItem < NumMenuItems - 1))\r
+        CurMenuItem++;\r
+    if(CurMenuItem < StartMenuItem)\r
+        StartMenuItem = CurMenuItem;\r
+    if(CurMenuItem >= (StartMenuItem + 18))\r
+        StartMenuItem = CurMenuItem - 17;\r
+    if(Key == 1)\r
+    {\r
+        if(MenuStackPos == 0)\r
+        {\r
+            Paused = MenuActive = 0;\r
+        } else {\r
+            LoadMenu(MenuStack[--MenuStackPos][0]);\r
+            CurMenuItem = MenuStack[MenuStackPos][1];\r
+            StartMenuItem = MenuStack[MenuStackPos][2];\r
+        }\r
+    }\r
+    if(Key == 28)\r
+    {\r
+        switch(*MenuItems[0][CurMenuItem])\r
+        {\r
+            case 0:\r
+                MenuStack[MenuStackPos][0] = MenuID;\r
+                MenuStack[MenuStackPos][1] = CurMenuItem;\r
+                MenuStack[MenuStackPos++][2] = StartMenuItem;\r
+                LoadMenu((unsigned short)MenuItems[0][CurMenuItem][1]);\r
+                CurMenuItem = StartMenuItem = 0;\r
+                break;\r
+            case 1:\r
+                if(InitVar() == 1)\r
+                {\r
+                    MessageBox("Couldn't find the control files PLAYER1.CTR and PLAYER2.CTR!");\r
+                    return(1);\r
+                }\r
+                if(LevelType == 0)\r
+                {\r
+                    if(LoadLevel(LevelFileName) != 0)\r
+                        LevelType = 1;\r
+                }\r
+                if(LevelType == 1)\r
+                {\r
+                    ReInit();\r
+                    RandomLevel();\r
+                }\r
+                if(LevelType == 2)\r
+                {\r
+                    ReInit();\r
+                    for(i = 0; i < 2; i++)\r
+                    {\r
+                        for(y = 0; y < LevelHeight; y++)\r
+                        {\r
+                            for(x = 0; x < LevelWidth; x++)\r
+                            {\r
+                                SetMapPixel((signed short)x, (signed short)y, (unsigned char)((i == 0)?0:7), i);\r
+                            }\r
+                        }\r
+                    }\r
+                    strcpy(LevelFileName, "Empty");\r
+                    DispLevelWidth = LevelWidth;\r
+                    DispLevelHeight = LevelHeight;\r
+                    SpawnObject(0, -1, 0, 0, 0, 0);\r
+                }\r
+                Paused = 0;\r
+                MenuActive = 0;\r
+                if(ModFileName == NULL)\r
+                {\r
+                    PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
+                } else {\r
+                    if(OpenFile(ModFileName, &ModFile) == 0)\r
+                    {\r
+                        PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
+                    } else {\r
+                        if(LoadMod(&ModFile) != 0)\r
+                            PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
+                        else\r
+                            ModPlaying = 1;\r
+                        FileClose(&ModFile);\r
+                    }\r
+                }\r
+                LevelFinished = 0;\r
+                return(0);\r
+            case 2:\r
+                return(1);\r
+            case 3:\r
+                if(UseSound == 1)\r
+                {\r
+                    TerminatePlayBack();\r
+                    if(SBReset() == 0)\r
+                    {\r
+                        ReadyBuffer = 0;\r
+                        BufferReady = 0;\r
+                        FillBuffer();\r
+                        ReadyBuffer = 1;\r
+                        StartPlayBack();\r
+                    } else {\r
+                        UseSound = 0;\r
+                    }\r
+                }\r
+                break;\r
+            case 4:\r
+                LoadMenu(MenuStack[--MenuStackPos][0]);\r
+                CurMenuItem = MenuStack[MenuStackPos][1];\r
+                StartMenuItem = MenuStack[MenuStackPos][2];\r
+                break;\r
+            case 5:\r
+                MenuStack[MenuStackPos][0] = MenuID;\r
+                MenuStack[MenuStackPos][1] = CurMenuItem;\r
+                MenuStack[MenuStackPos++][2] = StartMenuItem;\r
+                CurMenuItem = StartMenuItem = 0;\r
+                MenuItems[0][0] = "\x06";\r
+                strcpy(MenuItems[1][0], "Random");\r
+                MenuItems[0][1] = "\x07";\r
+                strcpy(MenuItems[1][1], "Empty");\r
+                NumMenuItems = 2;\r
+               if((d = opendir(".")) != NULL)\r
+               {\r
+                   while((de = readdir(d)) != NULL)\r
+                   {\r
+                       if((l = strlen(de->d_name)) < 4)\r
+                           continue;\r
+                       if(!strcmp(de->d_name + l - 4, ".lev") ||\r
+                          !strcmp(de->d_name + l - 4, ".bmp"))\r
+                       {\r
+                           MenuItems[0][NumMenuItems] = "\x08";\r
+                           strcpy(MenuItems[1][NumMenuItems++], de->d_name);\r
+                       }\r
+                   }\r
+                   closedir(d);\r
+               }\r
+                MenuItems[0][NumMenuItems] = "\x04";\r
+                strcpy(MenuItems[1][NumMenuItems++], "Return");\r
+                break;\r
+            case 6:\r
+                LevelType = 1;\r
+                LoadMenu(MenuStack[--MenuStackPos][0]);\r
+                CurMenuItem = MenuStack[MenuStackPos][1];\r
+                StartMenuItem = MenuStack[MenuStackPos][2];\r
+                strcpy(LevelFileName, "Random");\r
+                DispLevelWidth = LevelWidth;\r
+                DispLevelHeight = LevelHeight;\r
+                break;\r
+            case 7:\r
+                LevelType = 2;\r
+                LoadMenu(MenuStack[--MenuStackPos][0]);\r
+                CurMenuItem = MenuStack[MenuStackPos][1];\r
+                StartMenuItem = MenuStack[MenuStackPos][2];\r
+                strcpy(LevelFileName, "Empty");\r
+                DispLevelWidth = LevelWidth;\r
+                DispLevelHeight = LevelHeight;\r
+                break;\r
+            case 8:\r
+                if(OpenFile(MenuItems[1][CurMenuItem], &ModFile) == 0)\r
+                {\r
+                    sprintf(TextBuffer, "Couldn't open %s!", MenuItems[1][CurMenuItem]);\r
+                    MessageBox(TextBuffer);\r
+                    break;\r
+                }\r
+                FileRead((void *)&Signature, 2, &ModFile);\r
+                ValidLevel = 0;\r
+                if(Signature == 0x464B)\r
+                {\r
+                    ValidLevel = 1;\r
+                    FileRead((void *)&DispLevelWidth, 2, &ModFile);\r
+                    FileRead((void *)&DispLevelHeight, 2, &ModFile);\r
+                }\r
+                if(Signature == 0x4C4E)\r
+                {\r
+                    ValidLevel = 1;\r
+                    FileRead((void *)&DispLevelWidth, 2, &ModFile);\r
+                    FileRead((void *)&DispLevelHeight, 2, &ModFile);\r
+                }\r
+                if(Signature == 0x4D42)\r
+                {\r
+                    FileSkip(&ModFile, 16);\r
+                    ValidLevel = 1;\r
+                    FileRead((void *)&DispLevelWidth, 2, &ModFile);\r
+                    FileSkip(&ModFile, 2);\r
+                    FileRead((void *)&DispLevelHeight, 2, &ModFile);\r
+                }\r
+                if(ValidLevel == 0)\r
+                {\r
+                    sprintf(TextBuffer, "%s is not a valid level file!", MenuItems[1][CurMenuItem]);\r
+                    MessageBox(TextBuffer);\r
+                    break;\r
+                }\r
+                FileClose(&ModFile);\r
+                LevelType = 0;\r
+                strcpy(LevelFileName, MenuItems[1][CurMenuItem]);\r
+                LoadMenu(MenuStack[--MenuStackPos][0]);\r
+                CurMenuItem = MenuStack[MenuStackPos][1];\r
+                StartMenuItem = MenuStack[MenuStackPos][2];\r
+                break;\r
+        }\r
+    }\r
+    for(i = 0; ((i + StartMenuItem) < NumMenuItems) && (i < 18); i++)\r
+    {\r
+        FontPrint(MenuItems[1][i + StartMenuItem], 110, 40 + (i * 6), 0);\r
+        if((i + StartMenuItem) == CurMenuItem)\r
+        {\r
+            DBCopyBufferClipTrans(109 - Caches[30]->w, 42 + (i * 6) - ((Caches[30]->h - 1) >> 1), Caches[30]->Frames[0], Caches[30]->w, Caches[30]->h, 0, 0);\r
+            for(o = 109; o < 210; o += Caches[31]->w)\r
+                DBCopyBufferClipTrans(o, 42 + (i * 6) - ((Caches[31]->h - 1) >> 1), Caches[31]->Frames[0], Caches[31]->w, Caches[31]->h, 0, 0);\r
+            DBCopyBufferClipTrans(o, 42 + (i * 6) - ((Caches[30]->h - 1) >> 1), Caches[30]->Frames[1], Caches[30]->w, Caches[30]->h, 0, 0);\r
+        }\r
+    }\r
+    return(0);\r
+}\r
+\r
+unsigned char MonoColor(unsigned long c)\r
+{\r
+    Color Col;\r
+\r
+    Col = *(Color *)&c;\r
+    return((unsigned char)((Col.R + ((Col.G * 31) / 63) + Col.B) / 3));\r
+}\r
+\r
+unsigned long SmoothColor(unsigned long c1, unsigned long c2, unsigned long c3, unsigned long c4)\r
+{\r
+    Color Col0, Col1, Col2, Col3, Col4;\r
+\r
+    Col1 = *(Color *)&c1;\r
+    Col2 = *(Color *)&c2;\r
+    Col3 = *(Color *)&c3;\r
+    Col4 = *(Color *)&c4;\r
+    Col0.R = (Col1.R + Col2.R + Col3.R + Col4.R) >> 2;\r
+    Col0.G = (Col1.G + Col2.G + Col3.G + Col4.G) >> 2;\r
+    Col0.B = (Col1.B + Col2.B + Col3.B + Col4.B) >> 2;\r
+    return(*(unsigned long *)&Col0);\r
+}\r
+\r
+void SmoothArea(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2)\r
+{\r
+    unsigned short x, y;\r
+    unsigned long c0, a1, a2, a3, a4, s;\r
+\r
+    for(y = y1; y <= y2; y++)\r
+    {\r
+        for(x = x1; x <= x2; x++)\r
+        {\r
+            if(((GetMapPixel(x, y, 1) & MAP_WALKABLE) == 0) && ((GetMapPixel(x, y, 1) & MAP_DESTROYABLE) == MAP_DESTROYABLE))\r
+            {\r
+                a1 = GetMapPixel((signed short)x - 1, y, 1);\r
+                a2 = GetMapPixel(x + 1, y, 1);\r
+                a3 = GetMapPixel(x, (signed short)y - 1, 1);\r
+                a4 = GetMapPixel(x, y + 1, 1);\r
+                c0 = 0;\r
+                if((a1 & MAP_WALKABLE) == 0)\r
+                    c0++;\r
+                if((a2 & MAP_WALKABLE) == 0)\r
+                    c0++;\r
+                if((a3 & MAP_WALKABLE) == 0)\r
+                    c0++;\r
+                if((a4 & MAP_WALKABLE) == 0)\r
+                    c0++;\r
+                if(c0 == 0)\r
+                {\r
+                    SetMapPixel(x, y, MAP_WALKABLE | MAP_SHOOTABLE, 1);\r
+                    SpawnPixel(x, y, ((float)(rand() % 100) - 50) / 50, ((float)(rand() % 100) - 50) / 50, 255, 2, 0, 0, GetMapPixel(x, y, 0));\r
+                    SetMapPixel(x, y, 0, 0);\r
+                }\r
+                if(c0 < 4)\r
+                {\r
+                    s = SmoothColor(GetMapPixel(x + 1, y, 0), GetMapPixel(x - 1, y, 0), GetMapPixel(x, y + 1, 0), GetMapPixel(x, y - 1, 0));\r
+                    if(MonoColor(s) > 20)\r
+                        SetMapPixel(x, y, s, 0);\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void SpawnExplosion(signed short x, signed short y, unsigned char StartFrame, unsigned char Smokes, unsigned char Sound)\r
+{\r
+    unsigned short i, Result;\r
+\r
+    Result = SpawnSprite(0, x, y, 0, 0, 1, StartFrame++, 1);\r
+    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);\r
+    SmoothArea(x - Caches[0]->cx[StartFrame], y - Caches[0]->cy[StartFrame], x - Caches[0]->cx[StartFrame] + Caches[0]->w, y - Caches[0]->cy[StartFrame] + Caches[0]->h);\r
+    StartFrame--;\r
+    if(Smokes > 0)\r
+    {\r
+        for(i = 0; i < Smokes; i++)\r
+        {\r
+            SpawnSprite(1, x + ((signed short)(rand() % 10) - 5), y + ((signed short)(rand() % 10) - 5), 0, -1, 1, 0, 2);\r
+        }\r
+    }\r
+    if(Sound == 1)\r
+    {\r
+        if(StartFrame > 5)\r
+            PlaySound((rand() % 2) + 4, 0, 22, 42, 22050, 1);\r
+        else\r
+            PlaySound(3, 0, 43, 63, 22050, 1);\r
+    }\r
+}\r
+\r
+unsigned char ArgExist(unsigned short argc, unsigned char **argv, char *Match)\r
+{\r
+    unsigned short i;\r
+\r
+    for(i = 1; i < argc; i++)\r
+    {\r
+        if(strcasecmp(argv[i], Match) == 0)\r
+            return(i);\r
+    }\r
+    return(0);\r
+}\r
+\r
+int main(int argc, unsigned char **argv)\r
+{\r
+    unsigned short Result, x, y, i, o;\r
+    unsigned short Attributes;\r
+    signed short Size;\r
+    unsigned long Cycles;\r
+    unsigned char Finished;\r
+    unsigned char c0, c1, c2, c3, c4;\r
+    unsigned short w, h;\r
+    unsigned char MFR;\r
+    unsigned char Key;\r
+    unsigned long Start;\r
+    double TickCounts[5];\r
+    Color C0, C1, C2, C3, C4, FC;\r
+    ModEvent *Buffer;\r
+    KvidFile ModFile;\r
+    double StartTime, CurTime;\r
+    unsigned char NetFuncAddr[6];\r
+    unsigned char *RetBuffer;\r
+    float fcx[5], fcy[5];\r
+    float fcxi[5], fcyi[5];\r
+\r
+    //*(unsigned long *)&NetFuncAddr[0] = 0x0040102E;\r
+    //*(unsigned short *)&NetFuncAddr[4] = 0x0177;\r
+    //RetBuffer = (unsigned char *)MakeFarCall(0, NULL, NetFuncAddr);\r
+    DebugMode = 0;\r
+    MFR = 0;\r
+    c0 = c3 = 0;\r
+    w = h = 0;\r
+    if(argc > 1)\r
+    {\r
+        if(ArgExist(argc, argv, "/Debug") != 0)\r
+            DebugMode = 1;\r
+        if(ArgExist(argc, argv, "/FR") != 0)\r
+            MFR = 1;\r
+        if(ArgExist(argc, argv, "/Randomatiserad") != 0)\r
+            c0 = 1;\r
+        if(ArgExist(argc, argv, "/Empty") != 0)\r
+            c0 = 2;\r
+        if((c1 = (unsigned char)ArgExist(argc, argv, "/Bana")) != 0)\r
+            c0 = 3;\r
+        w = (unsigned short)ArgExist(argc, argv, "/Banbredd");\r
+        h = (unsigned short)ArgExist(argc, argv, "/Banaltitud");\r
+        if((c2 = (unsigned char)ArgExist(argc, argv, "/Bg")) != 0)\r
+            c3 = 1;\r
+    }\r
+    switch(Init(&Result))\r
+    {\r
+        case 0:\r
+            printf("SDL Failure\nQuitting...\n");\r
+            Terminate();\r
+            return(1);\r
+        case 1:\r
+            printf("VESA Failure\nQuitting...\n");\r
+            Terminate();\r
+            return(1);\r
+        case 2:\r
+            printf("Not enough memory!\n");\r
+            Terminate();\r
+            return(1);\r
+        case 3:\r
+            printf("Couldn't find the file KVID.DAT!\n");\r
+            Terminate();\r
+            return(1);\r
+        case 4:\r
+            printf("Datafile corrupted!\n");\r
+            Terminate();\r
+            return(1);\r
+    }\r
+    Players[0]->Used = 1;\r
+    Players[1]->Used = 1;\r
+    if(w > 0)\r
+        LevelWidth = (unsigned short)atoi(argv[w + 1]);\r
+    if(h > 0)\r
+        LevelHeight = (unsigned short)atoi(argv[h + 1]);\r
+    switch(c0)\r
+    {\r
+        case 0:\r
+            strcpy(LevelFileName, "dm.lev");\r
+            LevelType = 0;\r
+            if(LoadLevel("dm.lev") != 0)\r
+            {\r
+                RandomLevel();\r
+                LevelType = 1;\r
+            }\r
+            break;\r
+        case 1:\r
+            RandomLevel();\r
+            LevelType = 1;\r
+            break;\r
+        case 2:\r
+            for(i = 0; i < 2; i++)\r
+            {\r
+                for(y = 0; y < LevelHeight; y++)\r
+                {\r
+                    for(x = 0; x < LevelWidth; x++)\r
+                    {\r
+                        SetMapPixel((signed short)x, (signed short)y, (unsigned char)((i == 0)?0:7), i);\r
+                    }\r
+                }\r
+            }\r
+            strcpy(LevelFileName, "Empty");\r
+            SpawnObject(0, -1, 0, 0, 0, 0);\r
+            LevelType = 2;\r
+            break;\r
+        case 3:\r
+            strcpy(LevelFileName, argv[c1 + 1]);\r
+            LevelType = 0;\r
+            if(LoadLevel(argv[c1 + 1]) != 0)\r
+            {\r
+                RandomLevel();\r
+                LevelType = 1;\r
+            }\r
+            break;\r
+    }\r
+    if(InitVar() == 1)\r
+    {\r
+        Terminate();\r
+        printf("Couldn't find control files!\nShould be named PLAYER1.CTR and PLAYER2.CTR\n");\r
+        return(1);\r
+    }\r
+    ModFileName = NULL;\r
+    if(c3 == 0)\r
+    {\r
+        if(OpenFile("DefaultMod", &ModFile) == 0)\r
+        {\r
+            PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
+        } else {\r
+            if(LoadMod(&ModFile) != 0)\r
+            {\r
+                PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
+            } else {\r
+                ModPlaying = 1;\r
+                ModFileName = "DefaultMod";\r
+            }\r
+            FileClose(&ModFile);\r
+        }\r
+    } else {\r
+        if(OpenFile(argv[c2 + 1], &ModFile) == 0)\r
+        {\r
+            PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
+        } else {\r
+            if(LoadMod(&ModFile) != 0)\r
+            {\r
+                PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
+            } else {\r
+                ModPlaying = 1;\r
+                ModFileName = argv[c2 + 1];\r
+            }\r
+            FileClose(&ModFile);\r
+        }\r
+    }\r
+    if(MFR == 1)\r
+    {\r
+        Start = (unsigned long)time(NULL);\r
+        while((unsigned long)time(NULL) == Start);\r
+        Start = (unsigned long)time(NULL);\r
+    }\r
+    Paused = 0;\r
+    MenuActive = 0;\r
+    Cycles = 0;\r
+    Finished = 0;\r
+    LevelFinished = 0;\r
+    Size = 0;\r
+    StartTime = 0;\r
+    while(Finished == 0)\r
+    {\r
+       if(!MFR && !KeyTable[29])\r
+       {\r
+           CurTime = ntime();\r
+           while(CurTime - StartTime < 0.02)\r
+           {\r
+               usleep((unsigned long)((0.02 - (CurTime - StartTime)) * 1000000));\r
+               CurTime = ntime();\r
+           }\r
+       }\r
+       StartTime = ntime();\r
+       /*if(KeyTable[67] == 1)\r
+         DebugMode = 1;\r
+         if(KeyTable[68] == 1)\r
+         DebugMode = 0;*/\r
+       if(GetEvents())\r
+           Finished = 1;\r
+       for(i = 0; i < MAX_PLAYERS; i++)\r
+       {\r
+           Players[i]->Left = 0;\r
+           Players[i]->Right = 0;\r
+           Players[i]->Up = 0;\r
+           Players[i]->Down = 0;\r
+           Players[i]->Shoot = 0;\r
+           Players[i]->Change = 0;\r
+       }\r
+       GetInputs();\r
+       Key = ReadKey();\r
+       if(Paused == 0)\r
+           ControlPixels();\r
+       TickCounts[0] = ntime();\r
+       if(Paused == 0)\r
+           ControlSprites();\r
+       TickCounts[1] = ntime();\r
+       if(Paused == 0)\r
+           ControlObjects();\r
+       TickCounts[2] = ntime();\r
+       if(Paused == 0)\r
+           ControlPlayers();\r
+       TickCounts[3] = ntime();\r
+       Cycles++;\r
+       if(MFR == 1)\r
+           if((unsigned long)time(NULL) - Start > 10)\r
+               Finished = 1;\r
+       c0 = KeyTable[63] * 4;\r
+       if(KeyTable[64] == 1) c0 += 8;\r
+       if(KeyTable[65] == 1) c0 += 16;\r
+       if(KeyTable[59] == 1) BGFrame = c0;\r
+       if(KeyTable[60] == 1) BGFrame = c0 + 1;\r
+       if(KeyTable[61] == 1) BGFrame = c0 + 2;\r
+       if(KeyTable[62] == 1) BGFrame = c0 + 3;\r
+       if(KeyTable[66] == 1)\r
+       {\r
+           x = rand() % LevelWidth;\r
+           y = rand() % LevelHeight;\r
+           while((GetMapPixel(x, y, 1) & MAP_SHOOTABLE) == 0)\r
+           {\r
+               x = rand() % LevelWidth;\r
+               y = rand() % LevelHeight;\r
+           }\r
+           SpawnObject(145, -1, x, y, 0, 0);\r
+       }\r
+       if((Key == 1) && (LevelFinished == 0) && (MenuActive == 0))\r
+       {\r
+           LoadMenu(0);\r
+           MenuStackPos = 0;\r
+           CurMenuItem = StartMenuItem = 0;\r
+           Paused = MenuActive ^= 1;\r
+           Key = 0;\r
+       }\r
+       if(KeyTable[87] == 1)\r
+       {\r
+           while(KeyTable[87] == 1)\r
+               GetEvents();\r
+           Objects[Players[1]->Object]->xv = 100;\r
+       }\r
+       ControlMasks();\r
+       DrawScreen();\r
+       TickCounts[4] = ntime();\r
+       if(Key == 68)\r
+           SetMode(!FullScreen);\r
+       if(Key == 88)\r
+           SaveBitmap(DblBuffer, 320, 200, "ss.bmp");\r
+       if(MenuActive == 1)\r
+       {\r
+           if(ControlMenu(Key) == 1)\r
+               Finished = 1;\r
+       }\r
+       if((LevelFinished == 1) && ((MenuActive == 0) || (Paused == 0)))\r
+       {\r
+           LoadMenu(0);\r
+           CurMenuItem = StartMenuItem = 0;\r
+           Paused = MenuActive = 1;\r
+       }\r
+#if PLAY_TIME > 0\r
+       sprintf(TextBuffer, "Play time left: %li", (signed long)(PLAY_TIME - Cycles));\r
+       DBPrint(TextBuffer, 0, 196, 255);\r
+       if(Cycles >= PLAY_TIME)\r
+           Finished = 1;\r
+#endif\r
+       x = 0;\r
+       if(Cycles % 5 == 0)\r
+       {\r
+           if(--FogX < -Caches[FogSprite]->w)\r
+               FogX += Caches[FogSprite]->w;\r
+       }\r
+       if(Cycles % 10 == 0)\r
+       {\r
+           if(--FogY < -Caches[FogSprite]->h)\r
+               FogY += Caches[FogSprite]->h;\r
+       }\r
+       for(i = 0; i < 5; i++)\r
+       {\r
+           for(o = 0; o < (320 * ((TickCounts[i] - CurTime) / 0.02)); o++)\r
+           {\r
+               DBPSetC(x++, 199, MakeColor((i * 255) / 4, 0, ((4 - i) * 255) / 4));\r
+           }\r
+           CurTime = TickCounts[i];\r
+       }\r
+       if(KeyTable[203] == 1)\r
+           Size--;\r
+       if(KeyTable[205] == 1)\r
+           Size++;\r
+       if(Size < 0)\r
+           Size += 360;\r
+       if(Size >= 360)\r
+           Size -= 360;\r
+       //DBCopyBufferRotated(160, 100, Caches[47]->Frames[0], Caches[47]->w, Caches[47]->h, 0, Caches[47]->w >> 1, Caches[47]->h >> 1, Size);\r
+       DBPSetC(160, 100, MakeColor(255, 0, 0));\r
+       DisplayDB();\r
+    }\r
+    while(KeyTable[1] == 1)\r
+       GetEvents();\r
+    for(i = 0; i < 5; i++)\r
+    {\r
+        fcx[i] = (rand() % 320) + 1;\r
+        fcy[i] = (rand() % 200) + 1;\r
+        fcxi[i] = ((float)(rand() % 200) / 100) - 1;\r
+        fcyi[i] = ((float)(rand() % 200) / 100) - 1;\r
+    }\r
+    while(KeyTable[1] == 0)\r
+    {\r
+       GetEvents();\r
+        for(Start = 0; Start < 256000; Start += 4)\r
+        {\r
+            C0 = *(Color *)&DblBuffer[Start];\r
+           if(Start >= 4)\r
+               C1 = *(Color *)&DblBuffer[Start - 4];\r
+           if(Start < 255996)\r
+               C2 = *(Color *)&DblBuffer[Start + 4];\r
+           if(Start >= 1280)\r
+               C3 = *(Color *)&DblBuffer[Start - 1280];\r
+           if(Start < 254720)\r
+               C4 = *(Color *)&DblBuffer[Start + 1280];\r
+            FC.R = (C0.R + C1.R + C2.R + C3.R + C4.R) / 5;\r
+            FC.G = (C0.G + C1.G + C2.G + C3.G + C4.G) / 5;\r
+            FC.B = (C0.B + C1.B + C2.B + C3.B + C4.B) / 5;\r
+            *(unsigned long *)&DblBuffer[Start] = *(unsigned long *)&FC;\r
+        }\r
+        /*asm("\r
+        movl $0, %%eax\r
+        movd %%eax, %%mm2\r
+        movl $0, %%ecx\r
+        movd (%%edi), %%mm0\r
+        punpcklbw %%mm2, %%mm0\r
+        movd -1280(%%edi), %%mm1\r
+        emms\r
+        "\r
+        :\r
+        : "D" (DblBuffer)\r
+        : "%eax", "%ecx"\r
+        );*/\r
+        /*DBFCircleFadedTrans(fcx[0], fcy[0], 50, MakeColor(0, 100, 0), 1, 0);\r
+        DBFCircleFadedTrans(fcx[1], fcy[1], 50, MakeColor(0, 0, 100), 1, 0);\r
+        DBFCircleFadedTrans(fcx[2], fcy[2], 50, MakeColor(100, 100, 0), 1, 0);\r
+        DBFCircleFadedTrans(fcx[3], fcy[3], 50, MakeColor(100, 0, 50), 1, 0);\r
+        DBFCircleFadedTrans(fcx[4], fcy[4], 50, MakeColor(100, 0, 0), 1, 0);\r
+        for(i = 0; i < 5; i++)\r
+        {\r
+            fcx[i] += fcxi[i];\r
+            fcy[i] += fcyi[i];\r
+            if(fcx[i] > 270)\r
+                fcxi[i] = -fabs(fcxi[i]);\r
+            if(fcx[i] < 50)\r
+                fcxi[i] = fabs(fcxi[i]);\r
+            if(fcy[i] > 150)\r
+                fcyi[i] = -fabs(fcyi[i]);\r
+            if(fcy[i] < 50)\r
+                fcyi[i] = fabs(fcyi[i]);\r
+        }*/\r
+        DisplayDB();\r
+    }\r
+    Terminate();\r
+    printf("%lu\n", Cycles);\r
+    return(0);\r
+}\r
diff --git a/kvidha.h b/kvidha.h
new file mode 100644 (file)
index 0000000..e091eab
--- /dev/null
+++ b/kvidha.h
@@ -0,0 +1,377 @@
+#include <stdio.h>\r
+#include <malloc.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <math.h>\r
+\r
+#include "fileio.h"\r
+\r
+#define NUM_KEYS 9\r
+#define MAX_STACK 4096\r
+#define MAX_LINES 100\r
+#define NUM_MASKS 1\r
+#define MAX_PIXELS 5000\r
+#define NUM_COLORS 256\r
+#define NUM_PLANES 2\r
+#define NUM_SCRIPTS 5\r
+#define MAX_SPRITES 5000\r
+#define MAX_PLAYERS 16\r
+#define MAX_OBJECTS 3000\r
+#define NUM_WEAPONS 36\r
+#define MAX_SAMPLES 31\r
+#define MAX_HITTESTS 100\r
+#define MAX_CHANNELS 12\r
+#define MAX_PATTERNS 128\r
+#define MAX_SOUNDS 64\r
+#define SB_SIZE 1024\r
+#define PLAY_TIME 0\r
+#define SHOW_MAP 1\r
+#define TIMER_RES 1000\r
+\r
+#define MAP_SHOOTABLE 1\r
+#define MAP_WALKABLE 2\r
+#define MAP_DESTROYABLE 4\r
+#define MAP_TEMPORARY 8\r
+\r
+typedef struct ColorType\r
+{\r
+    unsigned char B;\r
+    unsigned char G;\r
+    unsigned char R;\r
+    unsigned char Reserved;\r
+} Color;\r
+\r
+typedef struct PixelType\r
+{\r
+    float x;\r
+    float y;\r
+    float xv;\r
+    float yv;\r
+    unsigned long c;\r
+    unsigned char SetColor;\r
+    unsigned char Explode;\r
+    signed short Damage;\r
+    unsigned char Owner;\r
+    unsigned char Used;\r
+} Pixel;\r
+\r
+typedef struct CacheType\r
+{\r
+    unsigned short w;\r
+    unsigned short h;\r
+    unsigned char NumFrames;\r
+    unsigned char **Frames;\r
+    signed short *cx;\r
+    signed short *cy;\r
+    unsigned char AnimDelay;\r
+} Cache;\r
+\r
+typedef struct SpriteType\r
+{\r
+    signed short x;\r
+    signed short y;\r
+    signed char xv;\r
+    signed char yv;\r
+    unsigned char AnimCount;\r
+    unsigned char AnimTimer;\r
+    unsigned char AnimDelay;\r
+    unsigned char CurFrame;\r
+    unsigned char Template;\r
+    unsigned char Transparent;\r
+    unsigned char Used;\r
+} Sprite;\r
+\r
+typedef struct WeaponType\r
+{\r
+    unsigned short Class;\r
+    unsigned short ReloadDelay;\r
+    unsigned short FireDelay;\r
+    unsigned short Ammo;\r
+    unsigned short MaxClips;\r
+    unsigned long Name;\r
+    unsigned short NameLength;\r
+} Weapon;\r
+\r
+typedef struct PWeaponType\r
+{\r
+    unsigned short Weapon;\r
+    unsigned short ReloadTimer;\r
+    unsigned short FireTimer;\r
+    unsigned short AmmoLeft;\r
+    unsigned short NumClips;\r
+    signed short Vars[4];\r
+    unsigned char Used;\r
+} PWeapon;\r
+\r
+typedef struct PlayerType\r
+{\r
+    unsigned char Visual;\r
+    unsigned short VPointX1;\r
+    unsigned short VPointY1;\r
+    unsigned short VPointX2;\r
+    unsigned short VPointY2;\r
+    unsigned short AMeterX1;\r
+    unsigned short AMeterY1;\r
+    unsigned short AMeterX2;\r
+    unsigned short AMeterY2;\r
+    unsigned short LMeterX1;\r
+    unsigned short LMeterY1;\r
+    unsigned short LMeterX2;\r
+    unsigned short LMeterY2;\r
+    unsigned short lx, ly;\r
+    unsigned short kx, ky;\r
+    unsigned short cx, cy;\r
+    unsigned short Object;\r
+    unsigned short VPObject;\r
+    unsigned char Keys[NUM_KEYS];\r
+    unsigned char HeldKeys[NUM_KEYS];\r
+    unsigned short KeyCodes[NUM_KEYS];\r
+    unsigned char Left;\r
+    unsigned char Right;\r
+    unsigned char Up;\r
+    unsigned char Down;\r
+    unsigned char Change;\r
+    unsigned char Shoot;\r
+    unsigned char JustShot;\r
+    signed short CurWeapon;\r
+    float Angle;\r
+    float AngleVel;\r
+    unsigned char Dir;\r
+    unsigned long CrossColor;\r
+    signed short Kills;\r
+    signed short Lives;\r
+    signed short Health;\r
+    signed short MaxHealth;\r
+    signed short PVars[40];\r
+    struct MaskType\r
+    {\r
+        unsigned char *Buffer;\r
+        unsigned char Method;\r
+        unsigned char Effects[16];\r
+    } Masks[NUM_MASKS];\r
+    unsigned char Used;\r
+} Player;\r
+\r
+typedef struct ClassType\r
+{\r
+    unsigned char *Code;\r
+    unsigned short Scripts[NUM_SCRIPTS];\r
+    unsigned char TickDelay;\r
+    unsigned char Sprite;\r
+    unsigned char StartFrame;\r
+    unsigned char RunHitTests;\r
+    unsigned char TouchDelay;\r
+    unsigned char TransSprite;\r
+    signed short GravityMod;\r
+} Class;\r
+\r
+typedef struct ObjectType\r
+{\r
+    float x;\r
+    float y;\r
+    float xv;\r
+    float yv;\r
+    unsigned short Class;\r
+    unsigned char TickTimer;\r
+    signed short Variables[6];\r
+    unsigned short SpriteLink;\r
+    unsigned char TouchTimer;\r
+    unsigned char Owner;\r
+    unsigned char Used;\r
+} Object;\r
+\r
+typedef struct LineType\r
+{\r
+    signed short x1, y1;\r
+    signed short x2, y2;\r
+    unsigned long c1, c2;\r
+    unsigned short Transparent;\r
+    unsigned char Used;\r
+} Line;\r
+\r
+typedef struct PalType\r
+{\r
+    unsigned char r;\r
+    unsigned char g;\r
+    unsigned char b;\r
+} Pal;\r
+\r
+typedef struct SoundType\r
+{\r
+    unsigned short Sound;\r
+    unsigned char Playing;\r
+    unsigned char Repeat;\r
+    float Volume;\r
+    unsigned long Offset;\r
+    unsigned long Pitch;\r
+    unsigned long PitchError;\r
+} Sound;\r
+\r
+typedef struct ModSampleType\r
+{\r
+    unsigned long SampleLen;\r
+    unsigned char FineTune;\r
+    unsigned char Volume;\r
+    unsigned long LoopStart;\r
+    unsigned long LoopLen;\r
+    unsigned char Allocated;\r
+    signed char *Buffer;\r
+} ModSample;\r
+\r
+typedef struct ModChannelType\r
+{\r
+    unsigned short Period;\r
+    unsigned short CurPeriod;\r
+    unsigned short OldPeriod;\r
+    unsigned char Volume;\r
+    unsigned char CurVolume;\r
+    unsigned char Sample;\r
+    unsigned long Offset;\r
+    unsigned char Looping;\r
+    unsigned char Playing;\r
+    unsigned long Reminder;\r
+    unsigned char Effect;\r
+    unsigned char Oscillation;\r
+    unsigned char OscAmp;\r
+    unsigned char OscFreq;\r
+    union\r
+    {\r
+        struct TwinNibbleType\r
+        {\r
+            unsigned char n1 : 4;\r
+            unsigned char n2 : 4;\r
+        } Nibbles;\r
+        unsigned char b;\r
+    } EffectData;\r
+} ModChannel;\r
+\r
+typedef struct ModEventType\r
+{\r
+    unsigned short Period;\r
+    unsigned char Sample;\r
+    unsigned char Effect;\r
+    unsigned char EffectData;\r
+} ModEvent;\r
+\r
+void SetMapPixel(unsigned short x, unsigned short y, unsigned long c, unsigned short Handle);\r
+unsigned long GetMapPixel(unsigned short x, unsigned short y, unsigned short Handle);\r
+void ShowMap(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned short MapX, unsigned short MapY);\r
+void SetMode(unsigned char Mode);\r
+unsigned char SeekData(unsigned char *ID);\r
+unsigned char LoadSprite(unsigned char *ID, unsigned short CacheNum);\r
+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 Transparent);\r
+unsigned char Init(unsigned short *Result);\r
+void Terminate(void);\r
+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 long c);\r
+void ControlSprites(void);\r
+void ControlPixels(void);\r
+unsigned char ArgExist(unsigned short argc, unsigned char **argv, char *Match);\r
+void CopyToMap(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char ColorPattern, unsigned char DestroyAll, unsigned short Attributes);\r
+void SpawnExplosion(signed short x, signed short y, unsigned char StartFrame, unsigned char Smokes, unsigned char Sound);\r
+unsigned short SpawnObject(unsigned short Class, unsigned char Owner, unsigned short x, unsigned short y, float xv, float yv);\r
+void ControlObjects(void);\r
+unsigned short WallAngle(unsigned short x, unsigned short y);\r
+void GetInputs(void);\r
+void DBPrint(unsigned char *Buffer, signed short x, signed short y, unsigned char bgc);\r
+void FontPrint(unsigned char *Buffer, signed short sx, signed short y, unsigned short bgc);\r
+unsigned char CollisionTest(signed short *x1, signed short *y1, signed short *x2, signed short *y2, unsigned char Pattern, unsigned char RunHitTests, unsigned short *ObjNum, unsigned char TestCache, unsigned short TestFrame);\r
+void DrawLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2, unsigned char Method, unsigned char UseSprite);\r
+unsigned short CalcAngle(signed short x1, signed short y1, signed short x2, signed short y2);\r
+void AddHitTest(unsigned short ObjNum);\r
+void RemoveHitTest(unsigned short ObjNum);\r
+void HurtRadius(signed short x, signed short y, signed short StartDamage, signed short StopDamage, unsigned short StartDecRadius, unsigned short StopRadius, unsigned char Owner);\r
+void CollVel(signed short x, signed short y, float *xv, float *yv, unsigned char Attributes);\r
+void MessageBox(unsigned char *Buffer);\r
+void FillBuffer(void);\r
+unsigned char PlaySound(unsigned short Sound, unsigned char Repeat, unsigned short StartSound, unsigned short EndSound, unsigned short Pitch, float Volume);\r
+unsigned long MakeColor(unsigned char R, unsigned char G, unsigned char B);\r
+unsigned char MonoColor(unsigned long c);\r
+void __inline GetNextLineCoord(signed short *x, signed short *y, signed short *d, unsigned short dx, unsigned short dy, signed short xi, signed short yi);\r
+void DrawLightning(signed short x1, signed short y1, signed short x2, signed short y2, unsigned short NumPoints, unsigned char Template);\r
+\r
+extern Pixel *Pixels[MAX_PIXELS];\r
+extern Cache **Caches;\r
+extern Sprite *Sprites[MAX_SPRITES];\r
+extern Object *Objects[MAX_OBJECTS];\r
+extern Player *Players[MAX_PLAYERS];\r
+extern PWeapon *PWeapons[MAX_PLAYERS][NUM_WEAPONS];\r
+extern Sound Sounds[MAX_SOUNDS];\r
+extern Class **Classes;\r
+extern Weapon **Weapons;\r
+extern unsigned char *Font;\r
+extern Line *Lines[MAX_LINES];\r
+extern unsigned long *SoundOffsets;\r
+extern unsigned short HitTests[MAX_HITTESTS];\r
+extern unsigned char *Strings;\r
+extern Pal Palette[NUM_COLORS];\r
+extern unsigned char ColorInfo[NUM_COLORS];\r
+extern KvidFile DataFile;\r
+extern float Gravity;\r
+extern unsigned char *VBuffer;\r
+extern unsigned char *DblBuffer;\r
+extern unsigned short VideoLDT;\r
+extern signed short clip_x1, clip_x2;\r
+extern signed short clip_y1, clip_y2;\r
+extern unsigned short PagesFree;\r
+extern unsigned short BGSprite, BGFrame;\r
+extern unsigned char LevelFinished;\r
+extern unsigned short LevelWidth, LevelHeight;\r
+extern unsigned short MaxLW, MaxLH;\r
+extern unsigned char  *LevelBuffer[NUM_PLANES];\r
+extern unsigned short NumSprites;\r
+extern unsigned short NumClasses;\r
+extern unsigned short NumWeapons;\r
+extern unsigned short NumSounds;\r
+extern unsigned char *SoundData;\r
+extern unsigned char DebugMode;\r
+extern unsigned short FrameRate;\r
+extern unsigned short FontSprite;\r
+extern signed short Regs[32];\r
+extern signed short GameVars[32];\r
+extern unsigned short StackPos;\r
+extern unsigned short Stack[MAX_STACK];\r
+extern unsigned char raw_key;\r
+extern unsigned char SpecialKey;\r
+extern volatile unsigned char ReadyToGo;\r
+extern unsigned short AsciiTable[256];\r
+extern unsigned char AsciiTable2[256];\r
+extern float Sine[360], Cosine[360];\r
+extern double PreSine[360], PreCosine[360];\r
+extern volatile unsigned char KeyTable[256];\r
+extern unsigned char RepeatKey;\r
+extern double RepeatData;\r
+extern unsigned short LastShot;\r
+extern unsigned char *TextBuffer;\r
+extern unsigned char *KeyboardBuffer;\r
+extern unsigned short KeybWritePos;\r
+extern unsigned char *SoundBuffer;\r
+extern signed short *TestBuffer;\r
+extern unsigned char UseSound;\r
+extern unsigned char FreeSound;\r
+extern unsigned short DSPAddress;\r
+extern unsigned char DMAChannel;\r
+extern unsigned char IRQLine;\r
+extern unsigned char OldMask;\r
+extern unsigned char DMAPage, DMAAddress, DMACount;\r
+extern unsigned char PICAddress;\r
+extern unsigned char ReadyBuffer, BufferReady;\r
+extern unsigned char Bit16, Stereo;\r
+extern unsigned short SBSampleRate;\r
+extern unsigned char NumPlays;\r
+extern unsigned short *FontBuffer;\r
+extern unsigned char ModeInfo[256];\r
+extern unsigned char *MenuBuffer;\r
+extern unsigned char Test;\r
+extern unsigned char FogSprite, FogX, FogY;\r
+extern void (*TransOps[5])(unsigned long *Bg, unsigned long Amount);\r
+extern ModSample Samples[MAX_SAMPLES];\r
+extern ModChannel Channels[MAX_CHANNELS];\r
+extern ModEvent *Patterns;\r
+extern unsigned char PatternOrder[MAX_PATTERNS];\r
+extern unsigned char ModPlaying, ModLen, ModRepeat, ModChannels;\r
+extern unsigned char ModPattern, ModRow;\r
+extern unsigned short ModOffset;\r
+extern unsigned char ModBPM, ModTPD;\r
+extern volatile unsigned long Ticks, TickError;\r
+extern unsigned char GameType;\r
+extern unsigned char BPP;\r
diff --git a/newdb.asm b/newdb.asm
new file mode 100644 (file)
index 0000000..f417e33
--- /dev/null
+++ b/newdb.asm
@@ -0,0 +1,197 @@
+.global _DBFillScreen\r
+_DBFillScreen:\r
+    push %edi\r
+    mov $64000, %ecx\r
+    mov 8(%esp), %eax\r
+    mov _DblBuffer, %edi\r
+    cld\r
+    rep stosl\r
+    pop %edi\r
+    ret\r
+\r
+.global _DBPSet\r
+_DBPSet:\r
+    mov 4(%esp), %ecx\r
+    mov 8(%esp), %edx\r
+    mov %edx, %eax\r
+    shl $8, %edx\r
+    shl $10, %eax\r
+    add %edx, %eax\r
+    lea _DblBuffer(%eax, %ecx, 4), %eax\r
+    mov 12(%esp), %edx\r
+    mov %edx, (%eax)\r
+    ret\r
+\r
+.global _DBPSetCAsm\r
+_DBPSetCAsm:\r
+    push %ebp\r
+    mov %esp, %ebp\r
+    mov 8(%ebp), %ecx\r
+    mov 12(%ebp), %edx\r
+    cmp (_clip_x1), %ecx\r
+    jl _DBPSetCAsmEnd\r
+    cmp (_clip_x2), %ecx\r
+    jg _DBPSetCAsmEnd\r
+    cmp (_clip_y1), %edx\r
+    jl _DBPSetCAsmEnd\r
+    cmp (_clip_y2), %edx\r
+    jg _DBPSetCAsmEnd\r
+    mov %edx, %eax\r
+    shl $8, %edx\r
+    shl $10, %eax\r
+    add %edx, %eax\r
+    lea _DblBuffer(%eax, %ecx, 4), %eax\r
+    mov 16(%ebp), %edx\r
+    mov %edx, (%eax)\r
+_DBPSetCAsmEnd:\r
+    pop %ebp\r
+    ret\r
+\r
+.global _DBCopyBufferAsm\r
+_DBCopyBufferAsm:\r
+    push %ebp\r
+    mov %esp, %ebp\r
+    mov 12(%ebp), %eax\r
+    mov $320, %ebx\r
+    mul %ebx\r
+    add 8(%ebp), %eax\r
+    shl $2, %eax\r
+    add _DblBuffer, %eax\r
+    mov %eax, %edi\r
+    mov 16(%ebp), %esi\r
+    mov 20(%ebp), %eax\r
+    mov $320, %ecx\r
+    sub %eax, %ecx\r
+    inc %eax\r
+    shl $2, %ecx\r
+    mov 28(%ebp), %ebx\r
+_DBCopyBufferLoop:\r
+    dec %eax\r
+    jz _DBCopyBufferRowEnd\r
+    mov (%esi), %edx\r
+    cmp %edx, %ebx\r
+    jz _DBCopyBufferAddOffsets\r
+    mov %edx, (%edi)\r
+_DBCopyBufferAddOffsets:\r
+    add $4, %esi\r
+    add $4, %edi\r
+    jmp _DBCopyBufferLoop\r
+_DBCopyBufferRowEnd:\r
+    decw 24(%ebp)\r
+    jz _DBCopyBufferEnd\r
+    mov 20(%ebp), %eax\r
+    inc %eax\r
+    add %ecx, %edi\r
+    jmp _DBCopyBufferLoop\r
+_DBCopyBufferEnd:\r
+    pop %ebp\r
+    ret\r
+\r
+.global _DisplayDBAsm\r
+_DisplayDBAsm:\r
+    push %ecx\r
+    push %esi\r
+    push %edi\r
+    mov $64000, %ecx\r
+    mov _DblBuffer, %esi\r
+    mov _VBuffer, %edi\r
+    cld\r
+    rep movsl\r
+    pop %edi\r
+    pop %esi\r
+    pop %ecx\r
+    /*dec %ecx\r
+_DisplayDBAsmLoop:\r
+    mov (%esi,%ecx,4), %eax\r
+    mov %eax, (%edi,%ecx,4)\r
+    dec %ecx\r
+    jnz _DisplayDBAsmLoop*/\r
+    ret\r
+\r
+.global _MakeFarCall\r
+_MakeFarCall:\r
+    movl 12(%esp), %ebx\r
+    movw 4(%ebx), %fs\r
+    movl (%ebx), %esi\r
+    movl %fs:(%esi), %eax\r
+    .byte 38                       /*CALL FAR HWORD PTR ES:[EBX]*/\r
+    .byte 255\r
+    .byte 27\r
+    ret\r
+\r
+.global _ColorAdd\r
+_ColorAdd:\r
+    push %esi\r
+    movd 12(%esp), %mm0\r
+    movl 8(%esp), %esi\r
+    movd (%esi), %mm1\r
+    paddusb %mm1, %mm0\r
+    movd %mm0, (%esi)\r
+    pop %esi\r
+    emms\r
+    ret\r
+\r
+.global _ColorSub\r
+_ColorSub:\r
+    push %esi\r
+    movd 12(%esp), %mm0\r
+    movl 8(%esp), %esi\r
+    movd (%esi), %mm1\r
+    psubusb %mm0, %mm1\r
+    movd %mm1, (%esi)\r
+    pop %esi\r
+    emms\r
+    ret\r
+\r
+.global _DBCopyBufferTransAsm\r
+_DBCopyBufferTrans:\r
+    push %ebp\r
+    movl %esp, %ebp\r
+    push %edi\r
+    push %esi\r
+    push %ecx\r
+    movl 12(%ebp), %edi\r
+    movl %edi, %eax\r
+    shll $10, %eax\r
+    shll $8, %edi\r
+    addl %eax, %edi\r
+    movl 8(%ebp), %eax\r
+    addl (_DblBuffer), %edi\r
+    leal (%edi, %eax, 4), %edi\r
+    movl 16(%ebp), %esi\r
+    movl $1280, %eax\r
+    movl 20(%ebp), %ebx\r
+    shll $2, %ebx\r
+    subl %ebx, %eax\r
+    push %eax\r
+    movl 32(%ebp), %eax\r
+    movl _TransOps(, %eax, 4), %eax\r
+    push %eax\r
+DBCopyBufferTransYLoop:\r
+    movl 20(%ebp), %ecx\r
+DBCopyBufferTransXLoop:\r
+    movl (%esi), %eax\r
+    cmpl 28(%ebp), %eax\r
+    je DBCopyBufferTransAddOffsets\r
+    push %ecx\r
+    push %edx\r
+    push %eax\r
+    push %edi\r
+    call *-20(%ebp)\r
+    add $8, %esp\r
+    pop %edx\r
+    pop %ecx\r
+DBCopyBufferTransAddOffsets:\r
+    add $4, %edi\r
+    add $4, %esi\r
+    loop DBCopyBufferTransXLoop\r
+    addl -16(%ebp), %edi\r
+    decl 24(%ebp)\r
+    jnz DBCopyBufferTransYLoop\r
+    add $8, %esp\r
+    pop %ecx\r
+    pop %esi\r
+    pop %edi\r
+    pop %ebp\r
+    ret\r
+\r
diff --git a/newdb.h b/newdb.h
new file mode 100644 (file)
index 0000000..9036154
--- /dev/null
+++ b/newdb.h
@@ -0,0 +1,8 @@
+void ColorAdd(unsigned long *Bg, unsigned long Amount);\r
+void ColorSub(unsigned long *Bg, unsigned long Amount);\r
+void DBCopyBufferAsm(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc);\r
+void DisplayDBAsm(void);\r
+void DBPSetCAsm(signed short x, signed short y, unsigned long c);\r
+void DBPSetAsm(signed short x, signed short y, unsigned long c);\r
+void DBFillScreen(unsigned long c);\r
+unsigned long MakeFarCall(unsigned long Message, void *Parameter, void *FuncAddr);\r
diff --git a/sb.c b/sb.c
new file mode 100644 (file)
index 0000000..75293c8
--- /dev/null
+++ b/sb.c
@@ -0,0 +1,193 @@
+#include <SDL/SDL.h>\r
+\r
+#include "dblbuf.h"\r
+#include "executor.h"\r
+#include "kvidha.h"\r
+\r
+static unsigned short SoundBufferPos;\r
+\r
+void StartPlayBack(void)\r
+{\r
+    SDL_PauseAudio(0);\r
+    return;\r
+}\r
+\r
+static void SBCallback(void *uudata, unsigned char *Buffer, int Length)\r
+{\r
+    unsigned short Pos, Cur, Left;\r
+    \r
+    Pos = 0;\r
+    while(Length > 0)\r
+    {\r
+       if(SoundBufferPos >= (SB_SIZE >> 1))\r
+       {\r
+           FillBuffer();\r
+           SoundBufferPos = 0;\r
+       }\r
+       Left = (SB_SIZE >> 1) - SoundBufferPos;\r
+       Cur = (Length > Left)?Left:Length;\r
+       memcpy(Buffer + Pos, SoundBuffer + SoundBufferPos, Cur);\r
+       Pos += Cur;\r
+       SoundBufferPos += Cur;\r
+       Length -= Cur;\r
+    }\r
+}\r
+\r
+unsigned char SBReset(void)\r
+{\r
+    SDL_AudioSpec my, got;\r
+    \r
+    SoundBufferPos = SB_SIZE;\r
+    my.freq = 44100;\r
+    my.format = AUDIO_U8;\r
+    my.channels = 1;\r
+    my.samples = SB_SIZE >> 1;\r
+    my.callback = SBCallback;\r
+    if(SDL_OpenAudio(&my, &got) < 0)\r
+    {\r
+       printf("Could not open SDL audio: %s\n", SDL_GetError());\r
+       return(1);\r
+    }\r
+    if((got.freq != 44100) ||\r
+       (got.format != AUDIO_U8) ||\r
+       (got.channels != 1))\r
+    {\r
+       printf("Audio format mismatch(%i %i %i)!\n", got.freq, got.format, got.channels);\r
+       return(1);\r
+    }\r
+    return(0);\r
+}\r
+\r
+void TerminatePlayBack(void)\r
+{\r
+    SDL_PauseAudio(1);\r
+    return;\r
+}\r
+\r
+/*void DSPOutput(unsigned char Value)\r
+{\r
+    while((inp(DSPAddress + 12) & 0x80) == 0x80);\r
+    outp(DSPAddress + 12, Value);\r
+}\r
+\r
+unsigned char DSPInput(void)\r
+{\r
+    while((inp(DSPAddress + 14) & 0x80) == 0);\r
+    return(inp(DSPAddress + 10));\r
+}\r
+\r
+void StartPlayBack(void)\r
+{\r
+    unsigned long PhysAddress;\r
+\r
+    PhysAddress = ((unsigned long)DOSSoundBuffer.rm_segment << 4);\r
+    outp((DMAChannel < 4)?10:0xD4, 4 | (DMAChannel & 3));\r
+    outp((DMAChannel < 4)?12:0xD8, 0);\r
+    outp((DMAChannel < 4)?11:0xD6, 0x58 | (DMAChannel & 3));\r
+    outp(DMAAddress, (unsigned char)(PhysAddress & 0xFF));\r
+    outp(DMAAddress, (unsigned char)((PhysAddress & 0xFF00) >> 8));\r
+    outp(DMAPage, (unsigned char)((PhysAddress & 0x0F0000) >> 16));\r
+    outp(DMACount, (unsigned char)((SB_SIZE - 1) & 0xFF));\r
+    outp(DMACount, (unsigned char)(((SB_SIZE - 1) & 0xFF00) >> 8));\r
+    outp((DMAChannel < 4)?10:0xD4, (DMAChannel & 3));\r
+    DSPOutput(0x40);\r
+    DSPOutput((unsigned char)(((65536 - (256000000 / ((unsigned long)SBSampleRate))) & 0xFF00) / 0x100));\r
+    DSPOutput(0x48);\r
+    DSPOutput((unsigned char)((SB_SIZE - 2) >> 1));\r
+    DSPOutput((unsigned char)((SB_SIZE - 2) >> 9));\r
+    DSPOutput(0x1C);\r
+}\r
+\r
+void SBInt(void)\r
+{\r
+    if(DMAChannel < 4)\r
+    {\r
+        inp(DSPAddress + 14);\r
+    } else {\r
+        outp(DSPAddress + 4, 0x82);\r
+        if((inp(DSPAddress + 5) & 2) == 2)\r
+            inp(DSPAddress + 15);\r
+    }\r
+    if(ReadyBuffer == 0)\r
+        ReadyBuffer = 1;\r
+    else\r
+        ReadyBuffer = 0;\r
+    BufferReady = 1;\r
+    FillBuffer();\r
+    outp(PICAddress, 0x20);\r
+}\r
+\r
+unsigned char SBReset(void)\r
+{\r
+    unsigned short i, Success;\r
+    unsigned long o;\r
+\r
+    Success = 0;\r
+    for(i = 0; (i < 5) && (Success == 0); i++)\r
+    {\r
+        outp(DSPAddress + 6, 1);\r
+        for(o = 0; o < 100000; o++);\r
+        outp(DSPAddress + 6, 0);\r
+        if(DSPInput() == 0xAA)\r
+            Success = 1;\r
+    }\r
+    if(Success == 0)\r
+        return(1);\r
+    switch(DMAChannel)\r
+    {\r
+        case 0:\r
+            DMAPage = 0x87;\r
+            break;\r
+        case 1:\r
+            DMAPage = 0x83;\r
+            break;\r
+        case 2:\r
+            DMAPage = 0x81;\r
+            break;\r
+        case 3:\r
+            DMAPage = 0x82;\r
+            break;\r
+        case 4:\r
+            DMAPage = 0x8F;\r
+            break;\r
+        case 5:\r
+            DMAPage = 0x8B;\r
+            break;\r
+        case 6:\r
+            DMAPage = 0x89;\r
+            break;\r
+        case 7:\r
+            DMAPage = 0x8A;\r
+            break;\r
+        default:\r
+            return(2);\r
+    }\r
+    if(DMAChannel < 4)\r
+    {\r
+        DMAAddress = DMAChannel << 1;\r
+        DMACount = (DMAChannel << 1) + 1;\r
+    } else {\r
+        DMAAddress = 0xC0 + ((DMAChannel - 4) << 2);\r
+        DMACount = 0xC2 + ((DMAChannel - 4) << 2);\r
+    }\r
+    PICAddress = (IRQLine >= 8)?0xA0:0x20;\r
+    outp(DSPAddress + 4, 10);\r
+    outp(DSPAddress + 5, 0);\r
+    outp(DSPAddress + 4, 4);\r
+    outp(DSPAddress + 5, 255);\r
+    outp(DSPAddress + 4, 34);\r
+    outp(DSPAddress + 5, 255);\r
+    DSPOutput(0xD1);\r
+    SetISR(IRQLine + ((IRQLine >= 8)?0x68:8), (unsigned long)SBInt, &NewSBInt, &OldSBInt);\r
+    OldMask = inp(PICAddress + 1);\r
+    outp(PICAddress + 1, OldMask & ~(1 << ((IRQLine >= 8)?(IRQLine - 8):IRQLine)));\r
+    return(0);\r
+}\r
+\r
+void TerminatePlayBack(void)\r
+{\r
+    DSPOutput((unsigned char)((DMAChannel < 4)?0xDA:0xD9));\r
+    outp(PICAddress + 1, OldMask);\r
+    ReturnISR(IRQLine + ((IRQLine >= 8)?0x68:8), &NewSBInt, &OldSBInt);\r
+}\r
+*/\r
diff --git a/sb.h b/sb.h
new file mode 100644 (file)
index 0000000..ce51c15
--- /dev/null
+++ b/sb.h
@@ -0,0 +1,9 @@
+void DSPOutput(unsigned char Value);\r
+unsigned char DSPInput(void);\r
+void StartPlayBack(void);\r
+void SBInt(void);\r
+unsigned char SBReset(void);\r
+void TerminatePlayBack(void);\r
+\r
+extern unsigned short SBSampleRate;\r
+\r
diff --git a/sdlmap.h b/sdlmap.h
new file mode 100644 (file)
index 0000000..3109df3
--- /dev/null
+++ b/sdlmap.h
@@ -0,0 +1,111 @@
+struct sdlmap {
+    int sdl, dos;
+    char *name;
+};
+
+struct sdlmap sdlmap[] = {
+    {8, 14, "BACKSPACE"},
+    {9, 15, "TAB"},
+    {13, 28, "RETURN"},
+    {27, 1, "ESCAPE"},
+    {32, 57, "SPACE"},
+    {39, 40, "QUOTE"},
+    {44, 51, "COMMA"},
+    {45, 12, "MINUS"},
+    {46, 52, "PERIOD"},
+    {47, 53, "SLASH"},
+    {48, 11, "0"},
+    {49, 2, "1"},
+    {50, 3, "2"},
+    {51, 4, "3"},
+    {52, 5, "4"},
+    {53, 6, "5"},
+    {54, 7, "6"},
+    {55, 8, "7"},
+    {56, 9, "8"},
+    {57, 10, "9"},
+    {59, 39, "SEMICOLON"},
+    {61, 13, "EQUALS"},
+    {91, 26, "LEFTBRACKET"},
+    {92, 43, "BACKSLASH"},
+    {93, 27, "RIGHTBRACKET"},
+    {96, 41, "BACKQUOTE"},
+    {97, 30, "a"},
+    {98, 48, "b"},
+    {99, 46, "c"},
+    {100, 32, "d"},
+    {101, 18, "e"},
+    {102, 33, "f"},
+    {103, 34, "g"},
+    {104, 35, "h"},
+    {105, 23, "i"},
+    {106, 36, "j"},
+    {107, 37, "k"},
+    {108, 38, "l"},
+    {109, 50, "m"},
+    {110, 49, "n"},
+    {111, 24, "o"},
+    {112, 25, "p"},
+    {113, 16, "q"},
+    {114, 19, "r"},
+    {115, 31, "s"},
+    {116, 20, "t"},
+    {117, 22, "u"},
+    {118, 47, "v"},
+    {119, 17, "w"},
+    {120, 45, "x"},
+    {121, 21, "y"},
+    {122, 44, "z"},
+    {127, 211, "DELETE"},
+    {256, 82, "KP0"},
+    {257, 79, "KP1"},
+    {258, 80, "KP2"},
+    {259, 81, "KP3"},
+    {260, 75, "KP4"},
+    {261, 76, "KP5"},
+    {262, 77, "KP6"},
+    {263, 71, "KP7"},
+    {264, 72, "KP8"},
+    {265, 73, "KP9"},
+    {266, 83, "KP_PERIOD"},
+    {267, 181, "KP_DIVIDE"},
+    {268, 55, "KP_MULTIPLY"},
+    {269, 74, "KP_MINUS"},
+    {270, 78, "KP_PLUS"},
+    {271, 156, "KP_ENTER"},
+    {273, 200, "UP"},
+    {274, 208, "DOWN"},
+    {275, 205, "RIGHT"},
+    {276, 203, "LEFT"},
+    {277, 210, "INSERT"},
+    {278, 199, "HOME"},
+    {279, 207, "END"},
+    {280, 201, "PAGEUP"},
+    {281, 209, "PAGEDOWN"},
+    {282, 59, "F1"},
+    {283, 60, "F2"},
+    {284, 61, "F3"},
+    {285, 62, "F4"},
+    {286, 63, "F5"},
+    {287, 64, "F6"},
+    {288, 65, "F7"},
+    {289, 66, "F8"},
+    {290, 67, "F9"},
+    {291, 68, "F10"},
+    {292, 87, "F11"},
+    {293, 88, "F12"},
+    {300, 69, "NUMLOCK"},
+    {301, 58, "CAPSLOCK"},
+    {302, 70, "SCROLLOCK"},
+    {303, 54, "RSHIFT"},
+    {304, 42, "LSHIFT"},
+    {305, 157, "RCTRL"},
+    {306, 29, "LCTRL"},
+    {307, 184, "RALT"},
+    {308, 56, "LALT"},
+    {311, 219, "LSUPER"},
+    {312, 220, "RSUPER"},
+    {316, 183, "PRINT"},
+    {319, 221, "MENU"},
+    {-1, -1, NULL}
+};