From 02f87e18acff0bc15499b1a9297ce407be69c2ef Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Fri, 23 Nov 2007 15:37:11 +0100 Subject: [PATCH] Initial commit --- Makefile | 10 + dblbuf.c | 1151 +++++++++++++++ dblbuf.h | 26 + executor.c | 849 +++++++++++ executor.h | 2 + fileio.c | 523 +++++++ fileio.h | 36 + kvidha.c | 4555 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kvidha.h | 377 +++++ newdb.asm | 197 +++ newdb.h | 8 + sb.c | 193 +++ sb.h | 9 + sdlmap.h | 111 ++ 14 files changed, 8047 insertions(+) create mode 100644 Makefile create mode 100644 dblbuf.c create mode 100644 dblbuf.h create mode 100644 executor.c create mode 100644 executor.h create mode 100644 fileio.c create mode 100644 fileio.h create mode 100644 kvidha.c create mode 100644 kvidha.h create mode 100644 newdb.asm create mode 100644 newdb.h create mode 100644 sb.c create mode 100644 sb.h create mode 100644 sdlmap.h 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} +}; -- 2.11.0