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