Fixed audio playing
[kvidha.git] / kvidha.c
1 #include <stdio.h>\r
2 #include <memory.h>\r
3 #include <malloc.h>\r
4 #include <stdlib.h>\r
5 #include <string.h>\r
6 #include <math.h>\r
7 #include <dirent.h>\r
8 #include <SDL/SDL.h>\r
9 \r
10 #include "fileio.h"\r
11 \r
12 #define NUM_KEYS 9\r
13 #define MAX_STACK 4096\r
14 #define MAX_LINES 1000\r
15 #define NUM_MASKS 1\r
16 #define MAX_PIXELS 5000\r
17 #define NUM_COLORS 256\r
18 #define NUM_PLANES 2\r
19 #define MAX_SOUNDS 64\r
20 #define MAX_RASTERS 100\r
21 #define NUM_SCRIPTS 5\r
22 #define MAX_SPRITES 5000\r
23 #define MAX_PLAYERS 16\r
24 #define MAX_OBJECTS 3000\r
25 #define NUM_WEAPONS 55\r
26 #define MAX_SAMPLES 31\r
27 #define MAX_OBJLISTS 16\r
28 #define MAX_HITTESTS 100\r
29 #define MAX_CHANNELS 12\r
30 #define MAX_PATTERNS 128\r
31 #define MAX_MENUITEMS 128\r
32 #define SB_SIZE 1024\r
33 #define PLAY_TIME 0\r
34 #define SHOW_MAP 1\r
35 #define CP_BLUR 0\r
36 \r
37 #define MAP_SHOOTABLE 1\r
38 #define MAP_WALKABLE 2\r
39 #define MAP_DESTROYABLE 4\r
40 #define MAP_TEMPORARY 8\r
41 \r
42 typedef struct ColorType\r
43 {\r
44     unsigned char B;\r
45     unsigned char G;\r
46     unsigned char R;\r
47     unsigned char Reserved;\r
48 } Color;\r
49 \r
50 typedef struct PixelType\r
51 {\r
52     float x;\r
53     float y;\r
54     float xv;\r
55     float yv;\r
56     unsigned long c;\r
57     unsigned char SetColor;\r
58     unsigned char Explode;\r
59     signed short Damage;\r
60     unsigned char Owner;\r
61     unsigned char Used;\r
62 } Pixel;\r
63 \r
64 typedef struct CacheType\r
65 {\r
66     unsigned short w;\r
67     unsigned short h;\r
68     unsigned char NumFrames;\r
69     unsigned char **Frames;\r
70     signed short *cx;\r
71     signed short *cy;\r
72     unsigned char AnimDelay;\r
73 } Cache;\r
74 \r
75 typedef struct SpriteType\r
76 {\r
77     signed short x;\r
78     signed short y;\r
79     signed char xv;\r
80     signed char yv;\r
81     unsigned char AnimCount;\r
82     unsigned char AnimTimer;\r
83     unsigned char AnimDelay;\r
84     unsigned char CurFrame;\r
85     unsigned char Template;\r
86     unsigned char Transparent;\r
87     unsigned char Used;\r
88 } Sprite;\r
89 \r
90 typedef struct WeaponType\r
91 {\r
92     unsigned short Class;\r
93     unsigned short ReloadDelay;\r
94     unsigned short FireDelay;\r
95     unsigned short Ammo;\r
96     unsigned short MaxClips;\r
97     unsigned long Name;\r
98     unsigned short NameLength;\r
99 } Weapon;\r
100 \r
101 typedef struct PWeaponType\r
102 {\r
103     unsigned short Weapon;\r
104     unsigned short ReloadTimer;\r
105     unsigned short FireTimer;\r
106     unsigned short AmmoLeft;\r
107     unsigned short NumClips;\r
108     signed short Vars[4];\r
109     unsigned char Used;\r
110 } PWeapon;\r
111 \r
112 typedef struct PlayerType\r
113 {\r
114     unsigned char Visual;\r
115     unsigned short VPointX1;\r
116     unsigned short VPointY1;\r
117     unsigned short VPointX2;\r
118     unsigned short VPointY2;\r
119     unsigned short AMeterX1;\r
120     unsigned short AMeterY1;\r
121     unsigned short AMeterX2;\r
122     unsigned short AMeterY2;\r
123     unsigned short LMeterX1;\r
124     unsigned short LMeterY1;\r
125     unsigned short LMeterX2;\r
126     unsigned short LMeterY2;\r
127     unsigned short lx, ly;\r
128     unsigned short kx, ky;\r
129     unsigned short cx, cy;\r
130     unsigned short Object;\r
131     unsigned short VPObject;\r
132     unsigned char Keys[NUM_KEYS];\r
133     unsigned char HeldKeys[NUM_KEYS];\r
134     unsigned short KeyCodes[NUM_KEYS];\r
135     unsigned char Left;\r
136     unsigned char Right;\r
137     unsigned char Up;\r
138     unsigned char Down;\r
139     unsigned char Change;\r
140     unsigned char Shoot;\r
141     unsigned char JustShot;\r
142     signed short CurWeapon;\r
143     float Angle;\r
144     float AngleVel;\r
145     unsigned char Dir;\r
146     unsigned long CrossColor;\r
147     signed short Kills;\r
148     signed short Lives;\r
149     signed short Health;\r
150     signed short MaxHealth;\r
151     signed short PVars[40];\r
152     struct MaskType\r
153     {\r
154         unsigned char *Buffer;\r
155         unsigned char Method;\r
156         unsigned char Effects[16];\r
157     } Masks[NUM_MASKS];\r
158     unsigned char Used;\r
159 } Player;\r
160 \r
161 typedef struct ClassType\r
162 {\r
163     unsigned char *Code;\r
164     unsigned short Scripts[NUM_SCRIPTS];\r
165     unsigned char TickDelay;\r
166     unsigned char Sprite;\r
167     unsigned char StartFrame;\r
168     unsigned char RunHitTests;\r
169     unsigned char TouchDelay;\r
170     unsigned char TransSprite;\r
171     signed short GravityMod;\r
172 } Class;\r
173 \r
174 typedef struct ObjectType\r
175 {\r
176     float x;\r
177     float y;\r
178     float xv;\r
179     float yv;\r
180     unsigned short Class;\r
181     unsigned char TickTimer;\r
182     signed short Variables[6];\r
183     unsigned short SpriteLink;\r
184     unsigned char TouchTimer;\r
185     unsigned char Owner;\r
186     unsigned char Used;\r
187 } Object;\r
188 \r
189 typedef struct ObjectListType\r
190 {\r
191     struct\r
192     {\r
193         unsigned short Object;\r
194         signed short x1, y1, x2, y2;\r
195     } Objects[MAX_OBJECTS + 1];\r
196     unsigned short NumObjects;\r
197     unsigned char Used;\r
198 } ObjectList;\r
199 \r
200 typedef struct LineType\r
201 {\r
202     signed short x1, y1;\r
203     signed short x2, y2;\r
204     unsigned long c1, c2;\r
205     unsigned short Transparent;\r
206     unsigned char UseSprite;\r
207     unsigned char AnimTimer;\r
208     unsigned char CurFrame;\r
209     unsigned char Used;\r
210 } Line;\r
211 \r
212 typedef struct RasterType\r
213 {\r
214     signed short x1, y1;\r
215     signed short x2, y2;\r
216     signed short x3, y3;\r
217     unsigned long Color;\r
218     unsigned char Transparent;\r
219     unsigned char Type;\r
220     unsigned char Used;\r
221 } Raster;\r
222 \r
223 typedef struct PalType\r
224 {\r
225     unsigned char r;\r
226     unsigned char g;\r
227     unsigned char b;\r
228 } Pal;\r
229 \r
230 typedef struct SoundCacheType\r
231 {\r
232     unsigned char *SoundBuffer;\r
233     unsigned long Length;\r
234 } SoundCache;\r
235 \r
236 typedef struct SoundType\r
237 {\r
238     unsigned short Sound;\r
239     unsigned char Playing;\r
240     unsigned char Repeat;\r
241     float Volume;\r
242     unsigned long Offset;\r
243     unsigned long Pitch;\r
244     unsigned long PitchError;\r
245 } Sound;\r
246 \r
247 typedef struct ModSampleType\r
248 {\r
249     unsigned long SampleLen;\r
250     unsigned char FineTune;\r
251     unsigned char Volume;\r
252     unsigned long LoopStart;\r
253     unsigned long LoopLen;\r
254     unsigned char Allocated;\r
255     signed char *Buffer;\r
256 } ModSample;\r
257 \r
258 typedef struct ModChannelType\r
259 {\r
260     unsigned short Period;\r
261     unsigned short CurPeriod;\r
262     unsigned short OldPeriod;\r
263     unsigned char Volume;\r
264     unsigned char CurVolume;\r
265     unsigned char Sample;\r
266     unsigned long Offset;\r
267     signed char LastSample;\r
268     unsigned char Looping;\r
269     unsigned char Playing;\r
270     unsigned long Reminder;\r
271     unsigned char Effect;\r
272     unsigned char Oscillation;\r
273     unsigned char OscAmp;\r
274     unsigned char OscFreq;\r
275     float OscOffset;\r
276     unsigned char OscWave;\r
277     unsigned char OscNoTrig;\r
278     union\r
279     {\r
280         struct TwinNibbleType\r
281         {\r
282             unsigned char n1 : 4;\r
283             unsigned char n2 : 4;\r
284         } Nibbles;\r
285         unsigned char b;\r
286     } EffectData;\r
287 } ModChannel;\r
288 \r
289 typedef struct ModEventType\r
290 {\r
291     unsigned short Period;\r
292     unsigned char Sample;\r
293     unsigned char Effect;\r
294     unsigned char EffectData;\r
295 } ModEvent;\r
296 \r
297 struct CodeType\r
298 {\r
299     signed short Parent, Size;\r
300     signed long Value;\r
301 } Codes[4096];\r
302 \r
303 void SetMapPixel(unsigned short x, unsigned short y, unsigned long c, unsigned short Handle);\r
304 unsigned long GetMapPixel(unsigned short x, unsigned short y, unsigned short Handle);\r
305 void ShowMap(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned short MapX, unsigned short MapY);\r
306 void SetMode(unsigned char Mode);\r
307 unsigned char SeekData(unsigned char *ID);\r
308 unsigned char LoadSprite(unsigned char *ID, unsigned short CacheNum);\r
309 unsigned short SpawnSprite(unsigned char Template, signed short x, signed short y, signed char xv, signed char yv, unsigned short AnimCount, unsigned char StartFrame, unsigned char Transparent);\r
310 unsigned char Init(unsigned short *Result);\r
311 void Terminate(void);\r
312 void SpawnPixel(unsigned short x, unsigned short y, float xv, float yv, unsigned char Owner, unsigned char SetColor, unsigned char Explode, signed short Damage, unsigned long c);\r
313 void ControlSprites(void);\r
314 void ControlPixels(void);\r
315 unsigned char ArgExist(unsigned short argc, unsigned char **argv, char *Match);\r
316 void CopyToMap(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char ColorPattern, unsigned char DestroyAll, unsigned short Attributes);\r
317 void SpawnExplosion(signed short x, signed short y, unsigned char StartFrame, unsigned char Smokes, unsigned char Sound);\r
318 unsigned short SpawnObject(unsigned short Class, unsigned char Owner, unsigned short x, unsigned short y, float xv, float yv);\r
319 void ControlObjects(void);\r
320 unsigned short WallAngle(unsigned short x, unsigned short y);\r
321 void GetInputs(void);\r
322 void DBPrint(unsigned char *Buffer, signed short x, signed short y, unsigned char bgc);\r
323 void FontPrint(unsigned char *Buffer, signed short sx, signed short y, unsigned short bgc);\r
324 unsigned char CollisionTest(signed short *x1, signed short *y1, signed short *x2, signed short *y2, unsigned char Pattern, unsigned char RunHitTests, unsigned short *ObjNum, unsigned char TestCache, unsigned short TestFrame);\r
325 void DrawLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2, unsigned char Method, unsigned char UseSprite);\r
326 unsigned short CalcAngle(signed short x1, signed short y1, signed short x2, signed short y2);\r
327 void AddHitTest(unsigned short ObjNum);\r
328 void RemoveHitTest(unsigned short ObjNum);\r
329 void HurtRadius(signed short x, signed short y, signed short StartDamage, signed short StopDamage, unsigned short StartDecRadius, unsigned short StopRadius, unsigned char Owner);\r
330 void CollVel(signed short x, signed short y, float *xv, float *yv, unsigned char Attributes);\r
331 void MessageBox(unsigned char *Buffer);\r
332 void FillBuffer(void);\r
333 unsigned char PlaySound(unsigned short Sound, unsigned char Repeat, unsigned short StartSound, unsigned short EndSound, unsigned long Pitch, float Volume);\r
334 unsigned long MakeColor(unsigned char R, unsigned char G, unsigned char B);\r
335 unsigned char MonoColor(unsigned long c);\r
336 void __inline GetNextLineCoord(signed short *x, signed short *y, signed short *d, unsigned short dx, unsigned short dy, signed short xi, signed short yi);\r
337 unsigned short GetObjectList(void);\r
338 \r
339 Pixel *Pixels[MAX_PIXELS];\r
340 Cache **Caches;\r
341 Sprite *Sprites[MAX_SPRITES];\r
342 Object *Objects[MAX_OBJECTS];\r
343 Player *Players[MAX_PLAYERS];\r
344 PWeapon *PWeapons[MAX_PLAYERS][NUM_WEAPONS];\r
345 ObjectList *ObjectLists[MAX_OBJLISTS];\r
346 Sound Sounds[MAX_SOUNDS];\r
347 SoundCache **SoundCaches;\r
348 Class **Classes;\r
349 Weapon **Weapons;\r
350 unsigned char *Font;\r
351 Line *Lines[MAX_LINES];\r
352 Raster *Rasters[MAX_RASTERS];\r
353 unsigned short HitTests[MAX_HITTESTS];\r
354 unsigned char *Strings;\r
355 Pal Palette[NUM_COLORS];\r
356 unsigned char ColorInfo[NUM_COLORS];\r
357 unsigned char *MenuItems[2][MAX_MENUITEMS];\r
358 unsigned short MenuStack[16][3], MenuStackPos;\r
359 KvidFile DataFile;\r
360 float Gravity;\r
361 SDL_Surface *VBuffer;\r
362 unsigned char *DblBuffer;\r
363 unsigned char FullScreen;\r
364 signed short clip_x1, clip_x2;\r
365 signed short clip_y1, clip_y2;\r
366 unsigned short PagesFree;\r
367 unsigned short BGSprite, BGFrame;\r
368 unsigned char LevelFinished;\r
369 unsigned short LevelWidth, LevelHeight;\r
370 unsigned short MaxLW, MaxLH;\r
371 unsigned char  *LevelBuffer[NUM_PLANES];\r
372 unsigned short NumSprites;\r
373 unsigned short NumClasses;\r
374 unsigned short NumWeapons;\r
375 unsigned short NumSounds;\r
376 unsigned char DebugMode;\r
377 unsigned short FrameRate;\r
378 unsigned short FontSprite;\r
379 signed short Regs[32];\r
380 signed short GameVars[40];\r
381 unsigned char StackPos;\r
382 unsigned short Stack[MAX_STACK];\r
383 unsigned char SpecialKey;\r
384 unsigned short AsciiTable[256];\r
385 unsigned char AsciiTable2[256];\r
386 float Sine[360], Cosine[360];\r
387 float WaveForms[5][360];\r
388 double PreSine[360], PreCosine[360];\r
389 volatile unsigned char KeyTable[256];\r
390 unsigned char RepeatKey;\r
391 double RepeatData;\r
392 unsigned char *TextBuffer;\r
393 unsigned char *KeyboardBuffer;\r
394 unsigned char *LevelFileName, *ModFileName;\r
395 unsigned char LevelType;\r
396 unsigned short DispLevelWidth, DispLevelHeight;\r
397 unsigned short KeybWritePos, KeybReadPos;\r
398 unsigned char *SoundBuffer;\r
399 signed short *TestBuffer;\r
400 unsigned char UseSound;\r
401 unsigned char FreeSound;\r
402 unsigned short DSPAddress;\r
403 unsigned char DMAChannel;\r
404 unsigned char IRQLine;\r
405 unsigned char OldMask;\r
406 unsigned char DMAPage, DMAAddress, DMACount;\r
407 unsigned char PICAddress;\r
408 unsigned char ReadyBuffer, BufferReady;\r
409 unsigned char Bit16, Stereo;\r
410 unsigned short SBSampleRate;\r
411 unsigned char NumPlays;\r
412 unsigned short *FontBuffer;\r
413 unsigned char ModeInfo[256];\r
414 unsigned char *MenuBuffer;\r
415 unsigned char FogSprite;\r
416 signed short FogX, FogY;\r
417 void (*TransOps[5])(unsigned long *Bg, unsigned long Amount);\r
418 ModSample Samples[MAX_SAMPLES];\r
419 ModChannel Channels[MAX_CHANNELS];\r
420 ModEvent *Patterns;\r
421 unsigned char PatternOrder[MAX_PATTERNS];\r
422 unsigned char ModPlaying, ModLen, ModRepeat, ModChannels;\r
423 unsigned char ModPattern, ModRow;\r
424 unsigned short ModOffset;\r
425 unsigned char ModBPM, ModTPD;\r
426 unsigned char MenuActive;\r
427 unsigned short NumMenuItems, CurMenuItem, StartMenuItem, MenuID;\r
428 unsigned char GameType;\r
429 unsigned char BPP;\r
430 unsigned char Paused;\r
431 unsigned short CurNew, CurComp;\r
432 \r
433 #include "sdlmap.h"\r
434 #include "newdb.h"\r
435 #include "dblbuf.h"\r
436 #include "executor.h"\r
437 #include "sb.h"\r
438 \r
439 /*\r
440 void NewKeyInt()\r
441 {\r
442     unsigned char Data;\r
443 \r
444     raw_key = inp(0x60);\r
445     Data = inp(0x61) | 0x82;\r
446     outp(0x61, Data);\r
447     outp(0x61, Data & 0x7F);\r
448     outp(0x20, 0x20);\r
449     if(raw_key < 128)\r
450     {\r
451         if(SpecialKey == 1)\r
452         {\r
453             KeyTable[raw_key + 128] = 1;\r
454             SpecialKey = 0;\r
455             RepeatKey = raw_key + 128;\r
456             RepeatData = 250;\r
457             KeyboardBuffer[KeybWritePos++] = raw_key + 128;\r
458             if(KeybWritePos >= 500)\r
459                 KeybWritePos = 0;\r
460         } else {\r
461             KeyTable[raw_key] = 1;\r
462             RepeatKey = raw_key;\r
463             RepeatData = 250;\r
464             KeyboardBuffer[KeybWritePos++] = raw_key;\r
465             if(KeybWritePos >= 500)\r
466                 KeybWritePos = 0;\r
467         }\r
468     } else {\r
469         if(raw_key == 0xE0)\r
470         {\r
471             SpecialKey = 1;\r
472         } else {\r
473             RepeatKey = 0;\r
474             if(SpecialKey == 1)\r
475             {\r
476                 KeyTable[raw_key] = 0;\r
477                 SpecialKey = 0;\r
478             } else {\r
479                 KeyTable[raw_key - 128] = 0;\r
480             }\r
481         }\r
482     }\r
483 }\r
484 */\r
485 \r
486 double ntime(void)\r
487 {\r
488     struct timeval tv;\r
489     \r
490     gettimeofday(&tv, NULL);\r
491     return((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0));\r
492 }\r
493 \r
494 unsigned char ReadKey(void)\r
495 {\r
496     unsigned char Data;\r
497 \r
498     if((Data = KeyboardBuffer[KeybReadPos]) != 0)\r
499     {\r
500         KeyboardBuffer[KeybReadPos] = 0;\r
501         if(++KeybReadPos >= 500)\r
502             KeybReadPos = 0;\r
503     }\r
504     return(Data);\r
505 }\r
506 \r
507 void EmptyKeyBuffer(void)\r
508 {\r
509     KeybWritePos = KeybReadPos = 0;\r
510     memset(KeyboardBuffer, 0, 500);\r
511 }\r
512 \r
513 void CopyToMap(signed short x, signed short y, unsigned char *Buffer, unsigned short w, unsigned short h, unsigned long bgc, unsigned char ColorPattern, unsigned char DestroyAll, unsigned short Attributes)\r
514 {\r
515     unsigned short cx, cy, i;\r
516     unsigned long data;\r
517     unsigned char c;\r
518     unsigned char Colors[NUM_COLORS];\r
519     unsigned char NumColors;\r
520 \r
521     NumColors = 0;\r
522     for(i = 0; i < NUM_COLORS; i++)\r
523     {\r
524         if(ColorInfo[i] == ColorPattern)\r
525             Colors[NumColors++] = i;\r
526     }\r
527     for(cy = 0; cy < h; cy++)\r
528     {\r
529         for(cx = 0; cx < w; cx++)\r
530         {\r
531             data = *(unsigned long *)Buffer;\r
532             Buffer += 4;\r
533             if(data != bgc)\r
534             {\r
535                 if(((GetMapPixel(x + cx, y + cy, 1) & MAP_DESTROYABLE) == MAP_DESTROYABLE) || (DestroyAll == 1))\r
536                 {\r
537                     if(Attributes != 0xFFFF)\r
538                         SetMapPixel(x + cx, y + cy, Attributes, 1);\r
539                     if(ColorPattern == 0)\r
540                         SetMapPixel(x + cx, y + cy, data, 0);\r
541                     else\r
542                     {\r
543                         c = Colors[rand() % NumColors];\r
544                         SetMapPixel(x + cx, y + cy, MakeColor(Palette[c].r, Palette[c].g, Palette[c].b), 0);\r
545                     }\r
546                 }\r
547             }\r
548         }\r
549     }\r
550 }\r
551 \r
552 void ReInit(void)\r
553 {\r
554     unsigned short i, o;\r
555 \r
556     for(i = 0; i < MAX_PIXELS; i++)\r
557         Pixels[i]->Used = 0;\r
558     for(i = 0; i < MAX_OBJECTS; i++)\r
559         Objects[i]->Used = 0;\r
560     for(i = 0; i < MAX_PLAYERS; i++)\r
561     {\r
562         for(o = 0; o < NUM_KEYS; o++)\r
563         {\r
564             Players[i]->Keys[o] = 0;\r
565             Players[i]->HeldKeys[o] = 0;\r
566         }\r
567     }\r
568     for(i = 0; i < MAX_SPRITES; i++)\r
569         Sprites[i]->Used = 0;\r
570     for(i = 0; i < MAX_LINES; i++)\r
571         Lines[i]->Used = 0;\r
572     for(i = 0; i < MAX_RASTERS; i++)\r
573         Rasters[i]->Used = 0;\r
574     for(i = 0; i < MAX_SOUNDS; i++)\r
575         Sounds[i].Playing = 0;\r
576     for(i = 0; i < MAX_HITTESTS; i++)\r
577         HitTests[i] = 0xFFFF;\r
578     ModPlaying = 0;\r
579 }\r
580 \r
581 /*\r
582 void TimerInt(void)\r
583 {\r
584     Ticks++;\r
585     TickError += FrameRate;\r
586     if(TickError >= TIMER_RES)\r
587     {\r
588         ReadyToGo = 1;\r
589         TickError -= TIMER_RES;\r
590     }\r
591     if(RepeatKey != 0)\r
592     {\r
593         if(--RepeatData == 0)\r
594         {\r
595             KeyboardBuffer[KeybWritePos++] = RepeatKey;\r
596             if(KeybWritePos >= 500)\r
597                 KeybWritePos = 0;\r
598             RepeatData = 25;\r
599         }\r
600     }\r
601 }\r
602 */\r
603 \r
604 void SetMapPixel(unsigned short x, unsigned short y, unsigned long c, unsigned short Handle)\r
605 {\r
606     if((x >= LevelWidth) || (y >= LevelHeight))\r
607         return;\r
608     if(Handle == 0)\r
609         *(unsigned long *)&LevelBuffer[Handle][(x + (y * LevelWidth)) << 2] = c;\r
610     else\r
611         *(unsigned char *)&LevelBuffer[Handle][x + (y * LevelWidth)] = (unsigned short)c;\r
612 }\r
613 \r
614 unsigned long GetMapPixel(unsigned short x, unsigned short y, unsigned short Handle)\r
615 {\r
616     if((x >= LevelWidth) || (y >= LevelHeight))\r
617         return(0);\r
618     if(Handle == 0)\r
619         return(*(unsigned long *)&LevelBuffer[Handle][(x + (y * LevelWidth)) << 2]);\r
620     else\r
621         return((unsigned long)*(unsigned char *)&LevelBuffer[Handle][x + (y * LevelWidth)]);\r
622 }\r
623 \r
624 void ShowMap(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, unsigned short MapX, unsigned short MapY)\r
625 {\r
626     unsigned short Window;\r
627     unsigned short cwx, cwy;\r
628     signed short x, y;\r
629     unsigned short i;\r
630     unsigned short CurFrame;\r
631     unsigned char Template;\r
632 \r
633     if((MapX >= LevelWidth) || (MapY >= LevelHeight))\r
634         return;\r
635     DBSetClip(x1, y1, x2, y2);\r
636     cwx = (MapX / 2) % Caches[BGSprite]->w;\r
637     cwy = (MapY / 2) % Caches[BGSprite]->h;\r
638     #if CP_BLUR == 0\r
639     for(y = (signed short)(y1 - Caches[BGSprite]->h); y < (signed short)(y2 + Caches[BGSprite]->h); y += Caches[BGSprite]->h)\r
640     {\r
641         for(x = (signed short)(x1 - Caches[BGSprite]->w); x < (signed short)(x2 + Caches[BGSprite]->w); x += Caches[BGSprite]->w)\r
642         {\r
643             DBCopyBufferClip((signed short)x - cwx, (signed short)y - cwy, Caches[BGSprite]->Frames[BGFrame], Caches[BGSprite]->w, Caches[BGSprite]->h, -1);\r
644         }\r
645     }\r
646     #endif\r
647     DBCopyBufferClip((signed short)x1 - (signed short)MapX, (signed short)y1 - (signed short)MapY, LevelBuffer[0], LevelWidth, LevelHeight, 0);\r
648     //DBCopyMapBufferClip((signed short)x1 - (signed short)MapX, (signed short)y1 - (signed short)MapY, LevelBuffer[0], LevelBuffer[1], LevelWidth, LevelHeight);\r
649     for(i = 0; i < MAX_LINES; i++)\r
650     {\r
651         if(Lines[i]->Used > 0)\r
652         {\r
653             if(Lines[i]->UseSprite != 0xFF)\r
654             {\r
655                 if(Lines[i]->Transparent != 0)\r
656                     DBSpriteLineTrans(Lines[i]->x1 - MapX + x1 - Caches[Lines[i]->UseSprite]->cx[Lines[i]->CurFrame], Lines[i]->y1 - MapY + y1 - Caches[Lines[i]->UseSprite]->cy[Lines[i]->CurFrame], Lines[i]->x2 - MapX + x1 - Caches[Lines[i]->UseSprite]->cx[Lines[i]->CurFrame], Lines[i]->y2 - MapY + y1 - Caches[Lines[i]->UseSprite]->cy[Lines[i]->CurFrame], Caches[Lines[i]->UseSprite]->Frames[Lines[i]->CurFrame], Caches[Lines[i]->UseSprite]->w, Caches[Lines[i]->UseSprite]->h, Lines[i]->Transparent - 1);\r
657                 else\r
658                     DBSpriteLine(Lines[i]->x1 - MapX + x1 - Caches[Lines[i]->UseSprite]->cx[Lines[i]->CurFrame], Lines[i]->y1 - MapY + y1 - Caches[Lines[i]->UseSprite]->cy[Lines[i]->CurFrame], Lines[i]->x2 - MapY + x1 - Caches[Lines[i]->UseSprite]->cx[Lines[i]->CurFrame], Lines[i]->y2 - MapY + y1 - Caches[Lines[i]->UseSprite]->cy[Lines[i]->CurFrame], Caches[Lines[i]->UseSprite]->Frames[Lines[i]->CurFrame], Caches[Lines[i]->UseSprite]->w, Caches[Lines[i]->UseSprite]->h);\r
659             } else {\r
660                 if(Lines[i]->Transparent != 0)\r
661                     DBLineTrans(Lines[i]->x1 - MapX + x1, Lines[i]->y1 - MapY + y1, Lines[i]->x2 - MapX + x1, Lines[i]->y2 - MapY + y1, Lines[i]->c1, Lines[i]->c2, Lines[i]->Transparent - 1);\r
662                 else\r
663                     DBLine(Lines[i]->x1 - MapX + x1, Lines[i]->y1 - MapY + y1, Lines[i]->x2 - MapX + x1, Lines[i]->y2 - MapY + y1, Lines[i]->c1, Lines[i]->c2);\r
664             }\r
665         }\r
666     }\r
667     for(i = 0; i < MAX_PIXELS; i++)\r
668     {\r
669         if(Pixels[i]->Used == 1)\r
670             DBPSetC((unsigned short)(Pixels[i]->x - MapX + x1), (unsigned short)(Pixels[i]->y - MapY + y1), Pixels[i]->c);\r
671     }\r
672     for(i = 0; i < MAX_SPRITES; i++)\r
673     {\r
674         if(Sprites[i]->Used == 1)\r
675         {\r
676             CurFrame = Sprites[i]->CurFrame;\r
677             Template = Sprites[i]->Template;\r
678             CurFrame %= Caches[Template]->NumFrames;\r
679             if(Sprites[i]->Transparent != 0)\r
680                 DBCopyBufferClipTrans((signed short)(Sprites[i]->x - MapX - Caches[Template]->cx[CurFrame] + x1), (signed short)(Sprites[i]->y - MapY - Caches[Template]->cy[CurFrame] + y1), Caches[Template]->Frames[CurFrame], Caches[Template]->w, Caches[Template]->h, 0, Sprites[i]->Transparent - 1);\r
681             else\r
682                 DBCopyBufferClip((signed short)(Sprites[i]->x - MapX - Caches[Template]->cx[CurFrame] + x1), (signed short)(Sprites[i]->y - MapY - Caches[Template]->cy[CurFrame] + y1), Caches[Template]->Frames[CurFrame], Caches[Template]->w, Caches[Template]->h, 0);\r
683         }\r
684     }\r
685     for(i = 0; i < MAX_RASTERS; i++)\r
686     {\r
687         if(Rasters[i]->Used == 1)\r
688         {\r
689             if(Rasters[i]->Type == 0)\r
690             {\r
691                 if(Rasters[i]->Transparent != 0)\r
692                     DBFPolyTrans(x1 - MapX + Rasters[i]->x1, y1 - MapY + Rasters[i]->y1, x1 - MapX + Rasters[i]->x2, y1 - MapY + Rasters[i]->y2, x1 - MapX + Rasters[i]->x3, y1 - MapY + Rasters[i]->y3, Rasters[i]->Color, Rasters[i]->Transparent - 1);\r
693                 else\r
694                     DBFPoly(x1 - MapX + Rasters[i]->x1, y1 - MapY + Rasters[i]->y1, x1 - MapX + Rasters[i]->x2, y1 - MapY + Rasters[i]->y2, x1 - MapX + Rasters[i]->x3, y1 - MapY + Rasters[i]->y3, Rasters[i]->Color);\r
695             }\r
696             if(Rasters[i]->Type == 1)\r
697             {\r
698                 if(Rasters[i]->Transparent != 0)\r
699                     DBFCircleTrans(x1 - MapX + Rasters[i]->x1, y1 - MapY + Rasters[i]->y1, Rasters[i]->x2, Rasters[i]->Color, 1, 1, Rasters[i]->Transparent - 1);\r
700                 else\r
701                     DBFCircle(x1 - MapX + Rasters[i]->x1, y1 - MapY + Rasters[i]->y1, Rasters[i]->x2, Rasters[i]->Color, 1, 1);\r
702             }\r
703         }\r
704     }\r
705     /*for(y = (signed short)(y1 - Caches[FogSprite]->h); y < (signed short)(y2 + Caches[FogSprite]->h); y += Caches[FogSprite]->h)\r
706     {\r
707         for(x = (signed short)(x1 - Caches[FogSprite]->w); x < (signed short)(x2 + Caches[FogSprite]->w); x += Caches[FogSprite]->w)\r
708         {\r
709             DBCopyBufferClipTrans((signed short)x - FogX, (signed short)y - FogY, Caches[FogSprite]->Frames[0], Caches[FogSprite]->w, Caches[FogSprite]->h, -1, 1);\r
710         }\r
711     }*/\r
712     DBSetClip(0, 0, 319, 199);\r
713 }\r
714 \r
715 unsigned char PlaySound(unsigned short Sound, unsigned char Repeat, unsigned short StartSound, unsigned short EndSound, unsigned long Pitch, float Volume)\r
716 {\r
717     unsigned short i;\r
718 \r
719     for(i = StartSound; i <= EndSound; i++)\r
720     {\r
721         if(Sounds[i].Playing == 0)\r
722         {\r
723             Sounds[i].Sound = Sound;\r
724             Sounds[i].Repeat = Repeat;\r
725             Sounds[i].Offset = 0;\r
726             Sounds[i].Pitch = Pitch;\r
727             Sounds[i].Volume = Volume;\r
728             Sounds[i].PitchError = 0;\r
729             Sounds[i].Playing = 1;\r
730             return(i);\r
731         }\r
732     }\r
733     return(0xFF);\r
734 }\r
735 \r
736 void InitCodeTable(void)\r
737 {\r
738     unsigned short i;\r
739 \r
740     CurComp = 1;\r
741     CurNew = 0;\r
742     for(i = 0; i < 4096; i++)\r
743     {\r
744         Codes[i].Parent = -1;\r
745         Codes[i].Size = -1;\r
746         Codes[i].Value = -1;\r
747     }\r
748 }\r
749 \r
750 signed short FindCode(signed long Value, signed short Parent)\r
751 {\r
752     unsigned short i;\r
753 \r
754     for(i = 0; i < (1 << CurComp); i++)\r
755     {\r
756         if((Codes[i].Value == Value) && (Codes[i].Parent == Parent))\r
757             return(i);\r
758     }\r
759     return(-1);\r
760 }\r
761 \r
762 unsigned long ReadVarLen(KvidFile *FileStr)\r
763 {\r
764     unsigned long Value;\r
765     unsigned char Finished, Shift;\r
766 \r
767     Value = 0;\r
768     Finished = Shift = 0;\r
769     while(Finished == 0)\r
770     {\r
771         if(FileReadBits(1, FileStr) == 1)\r
772             Finished = 1;\r
773         Value += FileReadBits(7, FileStr) << Shift;\r
774         Shift += 7;\r
775     }\r
776     return(Value);\r
777 }\r
778 \r
779 unsigned char AddCode(signed long Value, signed short Parent)\r
780 {\r
781     Codes[CurNew].Value = Value;\r
782     Codes[CurNew].Parent = Parent;\r
783     if(Parent == -1)\r
784         Codes[CurNew].Size = 0;\r
785     else\r
786         Codes[CurNew].Size = Codes[Parent].Size + 1;\r
787     if(++CurNew == (1 << CurComp))\r
788     {\r
789         if(++CurComp >= 13)\r
790         {\r
791             InitCodeTable();\r
792             return(1);\r
793         }\r
794     }\r
795     return(0);\r
796 }\r
797 \r
798 unsigned char LoadNewLevel(KvidFile *LevelFile)\r
799 {\r
800     unsigned short i, p, x, y;\r
801     unsigned short CC, CurCode;\r
802     signed short Parent, CodeNum, Length, RLECount;\r
803     signed long Col, LastCol;\r
804     unsigned char InRLE, InCode, SType, NoAdd, HasParent, ReInited;\r
805 \r
806     ReInit();\r
807     FileRead((void *)&LevelWidth, 2, LevelFile);\r
808     FileRead((void *)&LevelHeight, 2, LevelFile);\r
809     DispLevelWidth = LevelWidth;\r
810     DispLevelHeight = LevelHeight;\r
811     for(p = 0; p < 2; p++)\r
812     {\r
813         InitCodeTable();\r
814         Col = -1;\r
815         InRLE = InCode = 0;\r
816         NoAdd = 1;\r
817         HasParent = 0;\r
818         for(y = 0; y < LevelHeight; y++)\r
819         {\r
820             for(x = 0; x < LevelWidth; x++)\r
821             {\r
822                 LastCol = Col;\r
823                 if((InRLE == 0) && (InCode == 0))\r
824                 {\r
825                     InRLE = FileReadBits(1, LevelFile);\r
826                     SType = FileReadBits(2, LevelFile);\r
827                     if(InRLE == 1)\r
828                         RLECount = ReadVarLen(LevelFile);\r
829                     if(SType == 2)\r
830                     {\r
831                         InCode = 1;\r
832                         CurCode = FileReadBits(CurComp, LevelFile);\r
833                         Length = Codes[CurCode].Size;\r
834                         CC = CurCode;\r
835                         for(i = 0; i < Length; i++)\r
836                             CC = Codes[CC].Parent;\r
837                         Col = Codes[CC].Value;\r
838                     }\r
839                     if(SType == 0)\r
840                         Col = FileReadBits(16, LevelFile);\r
841                     if(NoAdd == 0)\r
842                     {\r
843                         if(HasParent == 0)\r
844                         {\r
845                             if((CodeNum = FindCode(LastCol, -1)) == -1)\r
846                             {\r
847                                 Parent = CurNew;\r
848                                 ReInited = AddCode(LastCol, -1);\r
849                             } else {\r
850                                 Parent = CodeNum;\r
851                                 ReInited = (FindCode(Col, CodeNum) == -1)?0:1;\r
852                             }\r
853                         } else {\r
854                             ReInited = 0;\r
855                         }\r
856                         HasParent = 0;\r
857                         if(ReInited == 0)\r
858                             AddCode(Col, Parent);\r
859                     }\r
860                     if(FindCode(Col, -1) == -1)\r
861                         AddCode(Col, -1);\r
862                     NoAdd = 0;\r
863                 }\r
864                 if(InCode == 1)\r
865                 {\r
866                     CC = CurCode;\r
867                     for(i = 0; i < Length; i++)\r
868                         CC = Codes[CC].Parent;\r
869                     Col = Codes[CC].Value;\r
870                     if(--Length < 0)\r
871                     {\r
872                         if(InRLE == 1)\r
873                         {\r
874                             if(--RLECount <= 0)\r
875                                 InRLE = InCode = 0;\r
876                             else\r
877                                 Length = Codes[CurCode].Size;\r
878                         } else {\r
879                             InCode = 0;\r
880                         }\r
881                         if(InCode == 0)\r
882                         {\r
883                             HasParent = 1;\r
884                             Parent = CurCode;\r
885                         }\r
886                     }\r
887                 } else {\r
888                     if(InRLE == 1)\r
889                     {\r
890                         if(--RLECount <= 0)\r
891                             InRLE = 0;\r
892                     }\r
893                 }\r
894                 if(p == 0)\r
895                     SetMapPixel(x, y, Color16To32((unsigned short)Col), p);\r
896                 else\r
897                     SetMapPixel(x, y, Col, p);\r
898             }\r
899         }\r
900     }\r
901     SpawnObject(0, -1, 0, 0, 0, 0);\r
902     FileClose(LevelFile);\r
903     return(0);\r
904 }\r
905 \r
906 unsigned char LoadBMPLevel(KvidFile *LevelFile)\r
907 {\r
908     unsigned short x, y;\r
909     unsigned long Buffer;\r
910     Color Col;\r
911 \r
912     ReInit();\r
913     FileSkip(LevelFile, 16);\r
914     FileRead((void *)&Buffer, 4, LevelFile);\r
915     LevelWidth = DispLevelWidth = (unsigned short)Buffer;\r
916     FileRead((void *)&Buffer, 4, LevelFile);\r
917     LevelHeight = DispLevelHeight = (unsigned short)Buffer;\r
918     FileSkip(LevelFile, 28);\r
919     for(y = LevelHeight; y > 0; y--)\r
920     {\r
921         for(x = 0; x < LevelWidth; x++)\r
922         {\r
923             FileRead((void *)&Col, 3, LevelFile);\r
924             Col.Reserved = 0;\r
925             SetMapPixel(x, y - 1, *(unsigned long *)&Col, 0);\r
926             if((Col.R == 0) && (Col.G == 0) && (Col.B == 0))\r
927             {\r
928                 SetMapPixel(x, y - 1, MAP_WALKABLE | MAP_SHOOTABLE, 1);\r
929             } else {\r
930                 if((Col.R == Col.G) && (Col.R == Col.B))\r
931                     SetMapPixel(x, y - 1, 0, 1);\r
932                 else\r
933                     SetMapPixel(x, y - 1, MAP_DESTROYABLE, 1);\r
934             }\r
935         }\r
936         FileSkip(LevelFile, LevelWidth % 4);\r
937     }\r
938     FileClose(LevelFile);\r
939     SpawnObject(0, -1, 0, 0, 0, 0);\r
940     return(0);\r
941 }\r
942 \r
943 unsigned char LoadLevel(unsigned char *Name)\r
944 {\r
945     KvidFile LevelFile, PalFile;\r
946     unsigned long Offset, Size;\r
947     unsigned short x, y, Count, Count2, Signature, i, o;\r
948     unsigned char Handle, RLEBase, c;\r
949     signed short ox, oy;\r
950     signed char Change, PalChange;\r
951     Color Col;\r
952 \r
953     DBFRect(0, 0, 319, 199, MakeColor(0, 0, 0));\r
954     if(OpenFile(Name, &LevelFile) == 0)\r
955         return(1);\r
956     FileRead((void *)&Signature, 2, &LevelFile);\r
957     if(Signature == 0x4C4E)\r
958         return(LoadNewLevel(&LevelFile));\r
959     if(Signature == 0x4D42)\r
960         return(LoadBMPLevel(&LevelFile));\r
961     if(Signature != 0x464B)\r
962         return(2);\r
963     ReInit();\r
964     FileRead((void *)&LevelWidth, 2, &LevelFile);\r
965     PalChange = 0;\r
966     if(LevelWidth == 0)\r
967     {\r
968         FileRead((void *)&c, 1, &LevelFile);\r
969         FileRead((void *)TextBuffer, c, &LevelFile);\r
970         TextBuffer[c] = 0;\r
971         FileRead((void *)&LevelWidth, 2, &LevelFile);\r
972         if(OpenFile(TextBuffer, &PalFile) != 0)\r
973         {\r
974             PalChange = 1;\r
975             FileRead((void *)Palette, sizeof(Pal) * 256, &PalFile);\r
976             FileClose(&PalFile);\r
977         }\r
978     }\r
979     FileRead((void *)&LevelHeight, 2, &LevelFile);\r
980     DispLevelWidth = LevelWidth;\r
981     DispLevelHeight = LevelHeight;\r
982     FileRead((void *)&RLEBase, 1, &LevelFile);\r
983     Size = LevelWidth * LevelHeight;\r
984     for(Handle = 0; Handle < 2; Handle++)\r
985     {\r
986         x = 0;\r
987         y = 0;\r
988         Count = 0;\r
989         for(Offset = 0; Offset < Size; Offset++)\r
990         {\r
991             if(Count > 0)\r
992                 Count--;\r
993             if(Count == 0)\r
994             {\r
995                 c = FileGetChar(&LevelFile);\r
996                 if(c >= RLEBase)\r
997                 {\r
998                     Count = (c - RLEBase) + 1;\r
999                     c = FileGetChar(&LevelFile);\r
1000                 }\r
1001             }\r
1002             if((Offset & 0xFFFF) == 0)\r
1003             {\r
1004                 sprintf(TextBuffer, "Loading %s... %u%%\0", Name, (unsigned short)(50 * ((double)Offset / (double)Size)) + (Handle * 50));\r
1005                 DBPrint(TextBuffer, 0, 0, 255);\r
1006                 DisplayDB();\r
1007             }\r
1008             if(Handle == 0)\r
1009                 SetMapPixel(x, y, MakeColor(Palette[c].r, Palette[c].g, Palette[c].b), Handle);\r
1010             else\r
1011                 SetMapPixel(x, y, (unsigned long)c, Handle);\r
1012             if(++x >= LevelWidth)\r
1013             {\r
1014                 x = 0;\r
1015                 y++;\r
1016             }\r
1017         }\r
1018     }\r
1019     if(PalChange == 1)\r
1020     {\r
1021         if(OpenFile("DefaultPalette", &PalFile) != 0)\r
1022         {\r
1023             FileRead((void *)Palette, sizeof(Pal) * 256, &PalFile);\r
1024             FileClose(&PalFile);\r
1025         }\r
1026     }\r
1027     FileRead((void *)&Count, 2, &LevelFile);\r
1028     GameType = 255;\r
1029     for(i = 0; i < Count; i++)\r
1030     {\r
1031         FileRead((void *)&Signature, 2, &LevelFile);\r
1032         FileRead((void *)&x, 2, &LevelFile);\r
1033         FileRead((void *)&y, 2, &LevelFile);\r
1034         FileRead((void *)&Count2, 2, &LevelFile);\r
1035         for(o = 0; o < Count2; o++)\r
1036         {\r
1037             Regs[FileGetChar(&LevelFile) + (FileGetChar(&LevelFile) << 8)] = FileGetChar(&LevelFile) + (FileGetChar(&LevelFile) << 8);\r
1038         }\r
1039         SpawnObject(Signature, -1, x, y, 0, 0);\r
1040     }\r
1041     FileClose(&LevelFile);\r
1042     if(GameType == 255)\r
1043         SpawnObject(0, -1, 0, 0, 0, 0);\r
1044     /*for(Offset = 0; Offset < 300; Offset++)\r
1045     {\r
1046         x = (unsigned short)(rand() % LevelWidth);\r
1047         y = (unsigned short)(rand() % LevelWidth);\r
1048         while(GetMapPixel(x, y, 0) != MakeColor(Palette[6].r, Palette[6].g, Palette[6].b))\r
1049         {\r
1050             x = (unsigned short)(rand() % LevelWidth);\r
1051             y = (unsigned short)(rand() % LevelWidth);\r
1052         }\r
1053         for(oy = -1; oy <= 1; oy++)\r
1054         {\r
1055             for(ox = -1; ox <= 1; ox++)\r
1056             {\r
1057                 Signature = GetMapPixel(x, y, 0);\r
1058                 Col = *(Color *)&Signature;\r
1059                 if((ox == 0) && (oy == 0))\r
1060                     Change = 3;\r
1061                 if((ox != 0) && (oy == 0) || (ox == 0) && (oy != 0))\r
1062                     Change = 2;\r
1063                 if((ox != 0) && (oy != 0))\r
1064                     Change = 1;\r
1065                 SetMapPixel((signed short)x + ox, (signed short)y + oy, MakeColor(Col.r - Change, Col.g - (Change << 1), Col.b - Change), 0);\r
1066                 sprintf(TextBuffer, "Loading %s... %u%%\0", Name, (unsigned short)(100 * ((double)Offset / (double)300)));\r
1067                 DBPrint(TextBuffer, 0, 0, 255);\r
1068                 DisplayDB();\r
1069             }\r
1070         }\r
1071     }*/\r
1072     return(0);\r
1073 }\r
1074 \r
1075 void RandomLevel(void)\r
1076 {\r
1077     unsigned short x, y, i, o;\r
1078     unsigned char c0, c1, c2, c3, c4;\r
1079 \r
1080     for(y = 0; y < LevelHeight; y++)\r
1081     {\r
1082         for(x = 0; x < LevelWidth; x++)\r
1083         {\r
1084             //SetMapPixel(x, y, (unsigned char)((rand() % 4) + 20), 0);\r
1085             SetMapPixel(x, y, 0, 0);\r
1086         }\r
1087     }\r
1088     for(y = 0; y < LevelHeight; y++)\r
1089     {\r
1090         for(x = 0; x < LevelWidth; x++)\r
1091         {\r
1092             SetMapPixel(x, y, MAP_WALKABLE | MAP_SHOOTABLE | MAP_DESTROYABLE, 1);\r
1093         }\r
1094     }\r
1095     for(i = 0; i < 75; i++)\r
1096     {\r
1097         x = rand() % LevelWidth;\r
1098         y = rand() % LevelHeight;\r
1099         CopyToMap(x - 15, y - 11, Caches[11]->Frames[rand() % Caches[11]->NumFrames], Caches[11]->w, Caches[11]->h, 0, 0, 0, 0);\r
1100     }\r
1101     for(i = 0; i < 150; i++)\r
1102     {\r
1103         x = rand() % LevelWidth;\r
1104         y = rand() % LevelHeight;\r
1105         CopyToMap(x - Caches[0]->cx[0], y - Caches[0]->cy[0], Caches[0]->Frames[0], Caches[0]->w, Caches[0]->h, 0, 3, 0, MAP_DESTROYABLE);\r
1106     }\r
1107     /*for(y = 0; y < LevelHeight; y++)\r
1108     {\r
1109         for(x = 0; x < LevelWidth; x++)\r
1110         {\r
1111             c0 = GetMapPixel(x, y, 0);\r
1112             if(c0 > 0)\r
1113             {\r
1114                 c1 = GetMapPixel(x - 1, y, 0);\r
1115                 c2 = GetMapPixel(x + 1, y, 0);\r
1116                 c3 = GetMapPixel(x, y - 1, 0);\r
1117                 c4 = GetMapPixel(x, y + 1, 0);\r
1118                 c1 = (c1 == 0)?c0:c1;\r
1119                 c2 = (c2 == 0)?c0:c2;\r
1120                 c3 = (c3 == 0)?c0:c3;\r
1121                 c4 = (c4 == 0)?c0:c4;\r
1122                 SetMapPixel(x, y, (unsigned char)((c1 + c2 + c3 + c4) >> 2), 0);\r
1123             }\r
1124         }\r
1125     }*/\r
1126     for(i = 0; i < 100; i++)\r
1127     {\r
1128         x = rand() % LevelWidth;\r
1129         y = rand() % LevelHeight;\r
1130         while((GetMapPixel(x, y, 1) & MAP_WALKABLE) == 0)\r
1131         {\r
1132             x = rand() % LevelWidth;\r
1133             y = rand() % LevelHeight;\r
1134         }\r
1135         while((GetMapPixel(x, y, 1) & MAP_WALKABLE) == MAP_WALKABLE)\r
1136             y++;\r
1137         c0 = rand() % Caches[12]->NumFrames;\r
1138         CopyToMap(x - Caches[12]->cx[c0], y - Caches[12]->cy[c0], Caches[12]->Frames[c0], Caches[12]->w, Caches[12]->h, 0, 0, 0, MAP_WALKABLE | MAP_TEMPORARY);\r
1139     }\r
1140     for(i = 0; i < 4; i++)\r
1141     {\r
1142         for(o = 0; o < 15; o++)\r
1143         {\r
1144             x = rand() % LevelWidth;\r
1145             y = rand() % LevelHeight;\r
1146             while((GetMapPixel(x, y, 1) & MAP_WALKABLE) == 0)\r
1147             {\r
1148                 x = rand() % (LevelWidth / 10);\r
1149                 y = rand() % (LevelHeight / 10);\r
1150             }\r
1151             if(i == 0)\r
1152                 while((GetMapPixel(x, ++y, 1) & MAP_WALKABLE) == MAP_WALKABLE);\r
1153             if(i == 1)\r
1154                 while((GetMapPixel(--x, y, 1) & MAP_WALKABLE) == MAP_WALKABLE);\r
1155             if(i == 2)\r
1156                 while((GetMapPixel(x, --y, 1) & MAP_WALKABLE) == MAP_WALKABLE);\r
1157             if(i == 3)\r
1158                 while((GetMapPixel(++x, y, 1) & MAP_WALKABLE) == MAP_WALKABLE);\r
1159             c0 = rand() % Caches[12]->NumFrames;\r
1160             Regs[0] = i;\r
1161             SpawnObject(93, -1, x, y, 0, 0);\r
1162         }\r
1163     }\r
1164     for(y = 0; y < LevelHeight; y++)\r
1165     {\r
1166         for(x = 0; x < LevelWidth; x++)\r
1167         {\r
1168             if((GetMapPixel(x, y, 1) & MAP_TEMPORARY) == MAP_TEMPORARY)\r
1169                 SetMapPixel(x, y, MAP_DESTROYABLE, 1);\r
1170         }\r
1171     }\r
1172     strcpy(LevelFileName, "Random");\r
1173     DispLevelWidth = LevelWidth;\r
1174     DispLevelHeight = LevelHeight;\r
1175     SpawnObject(0, -1, 0, 0, 0, 0);\r
1176 }\r
1177 \r
1178 void DrawScreen(void)\r
1179 {\r
1180     unsigned short i, o, cx, cy;\r
1181     signed short tx, ty, CurWeapon, x, y, x2, y2;\r
1182     float Per;\r
1183 \r
1184     #if CP_BLUR == 0\r
1185     DBFillScreen(0);\r
1186     #else\r
1187     DBFRectTrans(0, 0, 319, 199, MakeColor(16, 16, 16), 1);\r
1188     #endif\r
1189     for(i = 0; i < MAX_PLAYERS; i++)\r
1190     {\r
1191         if(Players[i]->Visual == 1)\r
1192         {\r
1193             x = Objects[Players[i]->VPObject]->x;\r
1194             y = Objects[Players[i]->VPObject]->y;\r
1195             cx = (Players[i]->VPointX2 - Players[i]->VPointX1) >> 1;\r
1196             cy = (Players[i]->VPointY2 - Players[i]->VPointY1) >> 1;\r
1197             if(x > LevelWidth - cx - 2) x = LevelWidth - cx - 2;\r
1198             if(y > LevelHeight - cy - 2) y = LevelHeight - cy - 2;\r
1199             if(x < cx) x = cx;\r
1200             if(y < cy) y = cy;\r
1201             ShowMap(Players[i]->VPointX1, Players[i]->VPointY1, Players[i]->VPointX2, Players[i]->VPointY2, x - cx, y - cy);\r
1202             //*(unsigned long *)(Players[i]->Masks[0].Buffer + ((((unsigned short)Objects[Players[i]->Object]->y - (y - cy)) * (Players[i]->VPointX2 - Players[i]->VPointX1 + 1) + ((unsigned short)Objects[Players[i]->Object]->x - (x - cx))) << 2)) = MakeColor(255, 0, 0);\r
1203             DBSetClip(Players[i]->VPointX1, Players[i]->VPointY1, Players[i]->VPointX2, Players[i]->VPointY2);\r
1204             for(o = 0; o < NUM_MASKS; o++)\r
1205             {\r
1206                 if(Players[i]->Masks[o].Method != 0)\r
1207                     DBCopyBufferClipTrans(Players[i]->VPointX1, Players[i]->VPointY1, Players[i]->Masks[o].Buffer, Players[i]->VPointX2 - Players[i]->VPointX1 + 1, Players[i]->VPointY2 - Players[i]->VPointY1 + 1, -1, Players[i]->Masks[o].Method - 1);\r
1208             }\r
1209             x2 = (unsigned short)((unsigned short)(Objects[Players[i]->Object]->x) + (Cosine[(unsigned short)Players[i]->Angle] * ((Players[i]->Dir == 0)?15:-15)) - x + cx + Players[i]->VPointX1 + ((Players[i]->Dir == 0)?3:-2));\r
1210             y2 = (unsigned short)((unsigned short)(Objects[Players[i]->Object]->y) - (Sine[(unsigned short)Players[i]->Angle] * 15) - y + cy + Players[i]->VPointY1 - 2);\r
1211             DBPSetCTrans(x2 - 1, y2, Players[i]->CrossColor, 2);\r
1212             DBPSetCTrans(x2 + 1, y2, Players[i]->CrossColor, 2);\r
1213             DBPSetCTrans(x2, y2 - 1, Players[i]->CrossColor, 2);\r
1214             DBPSetCTrans(x2, y2 + 1, Players[i]->CrossColor, 2);\r
1215             if(Players[i]->Change)\r
1216             {\r
1217                 tx = (signed short)(Objects[Players[i]->Object]->x - x + cx + Players[i]->VPointX1 - (Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->NameLength * 2));\r
1218                 ty = (signed short)(Objects[Players[i]->Object]->y - y + cy + Players[i]->VPointY1 - 20);\r
1219                 DBPrint((unsigned char *)&Strings[Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->Name], tx, ty, 0);\r
1220             }\r
1221             DBSetClip(0, 0, 319, 199);\r
1222             CurWeapon = Players[i]->CurWeapon;\r
1223             if(PWeapons[i][CurWeapon]->ReloadTimer == 0)\r
1224                 Per = (float)PWeapons[i][CurWeapon]->AmmoLeft / (float)Weapons[PWeapons[i][Players[i]->CurWeapon]->Weapon]->Ammo;\r
1225             else\r
1226                 Per = (float)PWeapons[i][CurWeapon]->ReloadTimer / (float)Weapons[PWeapons[i][CurWeapon]->Weapon]->ReloadDelay;\r
1227             if(Per > 0)\r
1228                 DBFRect(Players[i]->AMeterX1, Players[i]->AMeterY1, Players[i]->AMeterX1 + (signed short)(Per * (Players[i]->AMeterX2 - Players[i]->AMeterX1)), Players[i]->AMeterY2, MakeColor(255 - (Per * 255), 0, 255));\r
1229             Per = (float)Players[i]->Health / (float)Players[i]->MaxHealth;\r
1230             if(Per > 0)\r
1231             {\r
1232                 if(Per >= 0.5)\r
1233                     DBFRect(Players[i]->LMeterX1, Players[i]->LMeterY1, Players[i]->LMeterX1 + (signed short)(Per * (Players[i]->LMeterX2 - Players[i]->LMeterX1)), Players[i]->LMeterY2, MakeColor(255 - ((Per - 0.5) * 254), 255, 0));\r
1234                 else\r
1235                     DBFRect(Players[i]->LMeterX1, Players[i]->LMeterY1, Players[i]->LMeterX1 + (signed short)(Per * (Players[i]->LMeterX2 - Players[i]->LMeterX1)), Players[i]->LMeterY2, MakeColor(255, 510 * Per, 0));\r
1236             }\r
1237             sprintf(TextBuffer, "Lives: %i\0", Players[i]->Lives);\r
1238             DBPrint(TextBuffer, Players[i]->lx, Players[i]->ly, 255);\r
1239             sprintf(TextBuffer, "Kills: %i\0", Players[i]->Kills);\r
1240             DBPrint(TextBuffer, Players[i]->kx, Players[i]->ky, 255);\r
1241             if(Weapons[PWeapons[i][CurWeapon]->Weapon]->MaxClips > 0)\r
1242             {\r
1243                 sprintf(TextBuffer, "Ammo: %i\0", PWeapons[i][CurWeapon]->NumClips);\r
1244                 DBPrint(TextBuffer, Players[i]->cx, Players[i]->cy, 255);\r
1245             }\r
1246         }\r
1247     }\r
1248     DBPrint(TextBuffer, 319 - (sprintf(TextBuffer, "%s (%u x %u)", LevelFileName, DispLevelWidth, DispLevelHeight) * 4), 194, 255);\r
1249     sprintf(TextBuffer, "%l08X", GetMapPixel(Objects[Players[1]->Object]->x, Objects[Players[1]->Object]->y, KeyTable[2]));\r
1250     DBPrint(TextBuffer, 0, 194, 255);\r
1251     #if SHOW_MAP == 1\r
1252         for(y = 0; y < 40; y++)\r
1253         {\r
1254             for(x = 0; x < 64; x++)\r
1255             {\r
1256                 DBPSetCTrans(128 + x, 160 + y, GetMapPixel((float)x * ((float)LevelWidth / 64), (float)y * ((float)LevelHeight / 40), 0), 2);\r
1257             }\r
1258         }\r
1259         for(i = 0; i < MAX_PLAYERS; i++)\r
1260         {\r
1261             if(Players[i]->Used == 1)\r
1262             {\r
1263                DBPSetC(128 + (unsigned short)((float)Objects[Players[i]->Object]->x / ((float)LevelWidth / 64)), 160 + (unsigned short)((float)Objects[Players[i]->Object]->y / ((float)LevelHeight / 40)), MakeColor(200, 100, 0));\r
1264             }\r
1265         }\r
1266     #else\r
1267         DBCopyBufferClip(143, 180, Caches[15]->Frames[0], Caches[15]->w, Caches[15]->h, 0);\r
1268     #endif\r
1269 }\r
1270 \r
1271 unsigned short CalcAngle(signed short x1, signed short y1, signed short x2, signed short y2)\r
1272 {\r
1273     double a;\r
1274     unsigned char Q;\r
1275 \r
1276     if(x1 == x2)\r
1277     {\r
1278         if(y1 >= y2)\r
1279           return(90);\r
1280         if(y1 < y2)\r
1281           return(270);\r
1282     }\r
1283     a = atan((double)(y1 - y2) / (double)(x1 - x2));\r
1284     if(a < 0)\r
1285         a = -a;\r
1286     if((y1 >= y2) && (x1 < x2))\r
1287         Q = 0;\r
1288     if((y1 >= y2) && (x1 >= x2))\r
1289     {\r
1290         Q = 1;\r
1291         a = 1.570796 - a;\r
1292     }\r
1293     if((y1 < y2) && (x1 >= x2))\r
1294         Q = 2;\r
1295     if((y1 < y2) && (x1 < x2))\r
1296     {\r
1297         Q = 3;\r
1298         a = 1.570796 - a;\r
1299     }\r
1300     return((unsigned short)(((a + (Q * 1.570796)) / 3.141593) * 180));\r
1301 }\r
1302 \r
1303 unsigned long MakeColor(unsigned char R, unsigned char G, unsigned char B)\r
1304 {\r
1305     return(((unsigned short)R << 16) + ((unsigned short)G << 8) + (unsigned short)B);\r
1306 }\r
1307 \r
1308 unsigned char GetEvents(void)\r
1309 {\r
1310     unsigned short i;\r
1311     SDL_Event e;\r
1312     \r
1313     while(SDL_PollEvent(&e))\r
1314     {\r
1315         if(e.type == SDL_QUIT)\r
1316             return(1);\r
1317         if(e.type == SDL_KEYDOWN)\r
1318         {\r
1319             for(i = 0; sdlmap[i].sdl != -1; i++)\r
1320             {\r
1321                 if(sdlmap[i].sdl == e.key.keysym.sym)\r
1322                     break;\r
1323             }\r
1324             if(sdlmap[i].sdl != -1)\r
1325             {\r
1326                 KeyTable[sdlmap[i].dos] = 1;\r
1327                 RepeatKey = sdlmap[i].dos;\r
1328                 RepeatData = ntime() + 0.25;\r
1329                 KeyboardBuffer[KeybWritePos++] = sdlmap[i].dos;\r
1330                 if(KeybWritePos >= 500)\r
1331                     KeybWritePos = 0;\r
1332             }\r
1333         }\r
1334         if(e.type == SDL_KEYUP)\r
1335         {\r
1336             for(i = 0; sdlmap[i].sdl != -1; i++)\r
1337             {\r
1338                 if(sdlmap[i].sdl == e.key.keysym.sym)\r
1339                     break;\r
1340             }\r
1341             if(sdlmap[i].sdl != -1)\r
1342             {\r
1343                 KeyTable[sdlmap[i].dos] = 0;\r
1344                 RepeatKey = 0;\r
1345             }\r
1346         }\r
1347     }\r
1348     if((RepeatKey != 0) && (ntime() > RepeatData))\r
1349     {\r
1350         KeyboardBuffer[KeybWritePos++] = RepeatKey;\r
1351         if(KeybWritePos >= 500)\r
1352             KeybWritePos = 0;\r
1353         RepeatData = ntime() + 0.025;\r
1354     }\r
1355     return(0);\r
1356 }\r
1357 \r
1358 void GetInputs(void)\r
1359 {\r
1360     unsigned char i, o, u;\r
1361 \r
1362     for(i = 0; i < MAX_PLAYERS; i++)\r
1363     {\r
1364         for(o = 0; o < NUM_KEYS; o++)\r
1365         {\r
1366             if(((Players[i]->KeyCodes[o] & 0xFF00) == 0)?(KeyTable[Players[i]->KeyCodes[o]] == 1):((KeyTable[(Players[i]->KeyCodes[o] & 0xFF00) >> 8] == 1) && (KeyTable[Players[i]->KeyCodes[o] & 0x00FF] == 1)))\r
1367             {\r
1368                 if((Players[i]->Keys[o] == 0) && (Players[i]->HeldKeys[o] == 0))\r
1369                 {\r
1370                     Players[i]->Keys[o] = 1;\r
1371                 } else {\r
1372                     Players[i]->Keys[o] = 2;\r
1373                 }\r
1374             } else {\r
1375                 Players[i]->Keys[o] = 0;\r
1376             }\r
1377         }\r
1378         for(o = 0; o < NUM_KEYS; o++)\r
1379             Players[i]->HeldKeys[o] = 0;\r
1380         for(o = 0; o < NUM_KEYS; o++)\r
1381         {\r
1382             if(((Players[i]->KeyCodes[o] & 0xFF00) != 0) && (Players[i]->Keys[o] != 0))\r
1383             {\r
1384                 for(u = 0; u < NUM_KEYS; u++)\r
1385                 {\r
1386                     if((Players[i]->KeyCodes[u] == (Players[i]->KeyCodes[o] & 0x00FF)) || (Players[i]->KeyCodes[u] == ((Players[i]->KeyCodes[o] & 0xFF00) >> 8)))\r
1387                     {\r
1388                         Players[i]->Keys[u] = 0;\r
1389                         Players[i]->HeldKeys[u] = 1;\r
1390                     }\r
1391                 }\r
1392             }\r
1393         }\r
1394     }\r
1395 }\r
1396 \r
1397 void SetMode(unsigned char Mode)\r
1398 {\r
1399     if(FullScreen != Mode)\r
1400     {\r
1401         SDL_WM_ToggleFullScreen(VBuffer);\r
1402         FullScreen = Mode;\r
1403     }\r
1404     if(FullScreen == 0)\r
1405         SDL_ShowCursor(SDL_ENABLE);\r
1406     else\r
1407         SDL_ShowCursor(SDL_DISABLE);\r
1408 }\r
1409 \r
1410 void MessageBox(unsigned char *Buffer)\r
1411 {\r
1412     DBFRect(68, 88, 252, 112, MakeColor(255, 0, 0));\r
1413     DBFRect(69, 89, 251, 111, MakeColor(0, 0, 0));\r
1414     DBPrint(Buffer, 70, 90, 255);\r
1415     DisplayDB();\r
1416     while(KeyTable[57] == 1) GetEvents();\r
1417     while(KeyTable[57] == 0) GetEvents();\r
1418 }\r
1419 \r
1420 unsigned char LoadMod(KvidFile *ModFile)\r
1421 {\r
1422     unsigned short i, o, MaxPattern, Granularity, BkOffset;\r
1423     unsigned long Signature, BkAU, u;\r
1424     unsigned char Bytes[4], NumSamples, OldMod;\r
1425     ModEvent *Buffer;\r
1426 \r
1427     for(i = 0; i < MAX_SAMPLES; i++)\r
1428     {\r
1429         if(Samples[i].Allocated != 0)\r
1430         {\r
1431             Samples[i].Allocated = 0;\r
1432             free(Samples[i].Buffer);\r
1433         }\r
1434     }\r
1435     for(i = 0; i < MAX_CHANNELS; i++)\r
1436     {\r
1437         memset((void *)&Channels[i], 0, sizeof(ModChannel));\r
1438     }\r
1439     if((ModFile->DataFile == 1) || (ModFile->Parent != NULL))\r
1440     {\r
1441         BkAU = ModFile->CurAU;\r
1442         BkOffset = ModFile->Offset;\r
1443     } else {\r
1444         BkAU = ftell(ModFile->FilePtr);\r
1445     }\r
1446     FileSkip(ModFile, 1080);\r
1447     Signature = FileGetChar(ModFile);\r
1448     for(i = 0; i < 3; i++)\r
1449     {\r
1450         Signature <<= 8;\r
1451         Signature += FileGetChar(ModFile);\r
1452     }\r
1453     if((ModFile->DataFile == 1) || (ModFile->Parent != NULL))\r
1454     {\r
1455         ModFile->CurAU = BkAU;\r
1456         ModFile->Offset = BkOffset;\r
1457         ModFile->ReSeek = 1;\r
1458     } else {\r
1459         fseek(ModFile->FilePtr, BkAU, SEEK_SET);\r
1460     }\r
1461     FileSkip(ModFile, 20);\r
1462     ModChannels = 0;\r
1463     if((Signature == 0x4D2E4B2E) || (Signature == 0x4D214B21))          //"M.K." or "M!K!"\r
1464         ModChannels = 4;\r
1465     if(Signature == 0x3643484E)                                         //"6CHN"\r
1466         ModChannels = 6;\r
1467     if(Signature == 0x3843484E)                                         //"8CHN"\r
1468         ModChannels = 8;\r
1469     if(Signature == 0x31324348)                                         //"12CH"\r
1470         ModChannels = 12;\r
1471     if(ModChannels == 0)\r
1472     {\r
1473         ModChannels = 4;\r
1474         NumSamples = 15;\r
1475         OldMod = 1;\r
1476     } else {\r
1477         NumSamples = 31;\r
1478         OldMod = 0;\r
1479     }\r
1480     for(i = 0; i < NumSamples; i++)\r
1481     {\r
1482         FileSkip(ModFile, 22);\r
1483         Samples[i].SampleLen = ((FileGetChar(ModFile) << 8) + FileGetChar(ModFile)) << 1;\r
1484         Samples[i].FineTune = FileGetChar(ModFile) & 0x0F;\r
1485         Samples[i].Volume = FileGetChar(ModFile);\r
1486         Samples[i].LoopStart = (FileGetChar(ModFile) << 8) + FileGetChar(ModFile);\r
1487         Samples[i].LoopLen = (FileGetChar(ModFile) << 8) + FileGetChar(ModFile);\r
1488         if(OldMod == 0)\r
1489         {\r
1490             Samples[i].LoopStart <<= 1;\r
1491             Samples[i].LoopLen <<= 1;\r
1492         }\r
1493     }\r
1494     ModLen = FileGetChar(ModFile);\r
1495     if(ModLen > 128)\r
1496         ModLen = 128;\r
1497     ModRepeat = FileGetChar(ModFile);\r
1498     MaxPattern = 0;\r
1499     for(i = 0; i < 128; i++)\r
1500     {\r
1501         if((PatternOrder[i] = FileGetChar(ModFile)) > MaxPattern)\r
1502             MaxPattern = PatternOrder[i];\r
1503     }\r
1504     if(NumSamples > 15)\r
1505         FileSkip(ModFile, 4);\r
1506     Granularity = 64 * ModChannels;\r
1507     for(i = 0; i <= MaxPattern; i++)\r
1508     {\r
1509         for(o = 0; o < Granularity; o++)\r
1510         {\r
1511             Buffer = &Patterns[(i * Granularity) + o];\r
1512             FileRead((void *)Bytes, 4, ModFile);\r
1513             Buffer->Period = ((Bytes[0] & 0x0F) << 8) | Bytes[1];\r
1514             Buffer->Sample = (Bytes[0] & 0xF0) | ((Bytes[2] & 0xF0) >> 4);\r
1515             Buffer->Effect = Bytes[2] & 0x0F;\r
1516             Buffer->EffectData = Bytes[3];\r
1517         }\r
1518     }\r
1519     for(i = 0; i < NumSamples; i++)\r
1520     {\r
1521         if(Samples[i].SampleLen > 0)\r
1522         {\r
1523             //Samples[i].SampleLen = SoundCaches[15]->Length;\r
1524             if((Samples[i].Buffer = (unsigned char *)malloc(Samples[i].SampleLen)) == NULL)\r
1525                 return(2);\r
1526             FileRead((void *)Samples[i].Buffer, Samples[i].SampleLen, ModFile);\r
1527             //for(u = 0; u < Samples[i].SampleLen; u++)\r
1528             //    Samples[i].Buffer[u] = (signed char)((signed short)(SoundCaches[15]->SoundBuffer[u]) - 128);\r
1529             Samples[i].Allocated = 1;\r
1530         }\r
1531     }\r
1532     ModPattern = 0;\r
1533     ModRow = 0;\r
1534     ModOffset = 0;\r
1535     ModBPM = 125;\r
1536     ModTPD = 6;\r
1537     return(0);\r
1538 }\r
1539 \r
1540 unsigned char LoadSprite(unsigned char *ID, unsigned short CacheNum)\r
1541 {\r
1542     unsigned short i, o, Found;\r
1543     KvidFile SpriteFile;\r
1544 \r
1545     if(OpenFile(ID, &SpriteFile) == 0)\r
1546         return(1);\r
1547     FileRead((void *)&Caches[CacheNum]->w, 2, &SpriteFile);\r
1548     FileRead((void *)&Caches[CacheNum]->h, 2, &SpriteFile);\r
1549     FileRead((void *)&Caches[CacheNum]->NumFrames, 1, &SpriteFile);\r
1550     FileRead((void *)&Caches[CacheNum]->AnimDelay, 1, &SpriteFile);\r
1551     if((Caches[CacheNum]->cx = (signed short *)malloc(Caches[CacheNum]->NumFrames * 2)) == NULL)\r
1552         return(2);\r
1553     if((Caches[CacheNum]->cy = (signed short *)malloc(Caches[CacheNum]->NumFrames * 2)) == NULL)\r
1554         return(2);\r
1555     if((Caches[CacheNum]->Frames = (unsigned char **)malloc(Caches[CacheNum]->NumFrames * 4)) == NULL)\r
1556         return(2);\r
1557     for(o = 0; o < Caches[CacheNum]->NumFrames; o++)\r
1558     {\r
1559         FileRead((void *)&Caches[CacheNum]->cx[o], 2, &SpriteFile);\r
1560         FileRead((void *)&Caches[CacheNum]->cy[o], 2, &SpriteFile);\r
1561         if((Caches[CacheNum]->Frames[o] = (unsigned char *)malloc(Caches[CacheNum]->w * Caches[CacheNum]->h * 4)) == NULL)\r
1562             return(2);\r
1563         FileRead((void *)Caches[CacheNum]->Frames[o], Caches[CacheNum]->w * Caches[CacheNum]->h * 4, &SpriteFile);\r
1564     }\r
1565     FileClose(&SpriteFile);\r
1566     return(0);\r
1567 }\r
1568 \r
1569 unsigned short SpawnSprite(unsigned char Template, signed short x, signed short y, signed char xv, signed char yv, unsigned short AnimCount, unsigned char StartFrame, unsigned char Transparent)\r
1570 {\r
1571     unsigned short i;\r
1572 \r
1573     for(i = 0; i < MAX_SPRITES; i++)\r
1574     {\r
1575         if(Sprites[i]->Used == 0)\r
1576         {\r
1577             Sprites[i]->x = x;\r
1578             Sprites[i]->y = y;\r
1579             Sprites[i]->xv = xv;\r
1580             Sprites[i]->yv = yv;\r
1581             Sprites[i]->AnimTimer = 0;\r
1582             Sprites[i]->AnimCount = AnimCount;\r
1583             Sprites[i]->AnimDelay = Caches[Template]->AnimDelay;\r
1584             Sprites[i]->CurFrame = StartFrame;\r
1585             Sprites[i]->Template = Template;\r
1586             Sprites[i]->Transparent = Transparent;\r
1587             Sprites[i]->Used = 1;\r
1588             return(i);\r
1589         }\r
1590     }\r
1591     return(0xFFFF);\r
1592 }\r
1593 \r
1594 void FillBuffer(void)\r
1595 {\r
1596     unsigned short i, o;\r
1597     unsigned long Offset;\r
1598     signed short Data, Data2;\r
1599     unsigned short ModBPD;\r
1600     unsigned short SampleRate;\r
1601     unsigned char Temp;\r
1602     float Amp;\r
1603     ModEvent *Buffer;\r
1604 \r
1605     for(i = 0; i < SB_SIZE >> 1; i++)\r
1606     {\r
1607         SoundBuffer[i] = 128;\r
1608     }\r
1609     for(i = 0; i < MAX_SOUNDS; i++)\r
1610     {\r
1611         if(Sounds[i].Playing == 1)\r
1612         {\r
1613             for(o = 0; o < SB_SIZE >> 1; o++)\r
1614             {\r
1615                 Sounds[i].PitchError += Sounds[i].Pitch;\r
1616                 while(Sounds[i].PitchError >= SBSampleRate)\r
1617                 {\r
1618                     Sounds[i].PitchError -= SBSampleRate;\r
1619                     Sounds[i].Offset++;\r
1620                 }\r
1621                 if(Sounds[i].Offset >= SoundCaches[Sounds[i].Sound]->Length)\r
1622                 {\r
1623                     if(Sounds[i].Repeat == 0)\r
1624                     {\r
1625                         Sounds[i].Playing = 0;\r
1626                         break;\r
1627                     } else {\r
1628                         Sounds[i].Offset = 0;\r
1629                     }\r
1630                 }\r
1631                 Data = ((signed short)SoundBuffer[o] - 128);\r
1632                 Data += (((signed short)(SoundCaches[Sounds[i].Sound]->SoundBuffer[Sounds[i].Offset] - 128) * Sounds[i].Volume) / 4);\r
1633                 if(Data > 127)\r
1634                     Data = 127;\r
1635                 if(Data < -128)\r
1636                     Data = -128;\r
1637                 SoundBuffer[o] = (unsigned char)(Data + 128);\r
1638             }\r
1639         }\r
1640     }\r
1641     if(ModPlaying != 0)\r
1642     {\r
1643         ModBPD = (SBSampleRate * 5 * ModTPD) / (ModBPM * 2);\r
1644         if(KeyTable[5] == 1)\r
1645             ModBPD >>= 1;\r
1646         for(i = 0; i < SB_SIZE >> 1; i++)\r
1647         {\r
1648             Data2 = 0;\r
1649             for(o = 0; o < ModChannels; o++)\r
1650             {\r
1651                 if(ModOffset == 0)\r
1652                 {\r
1653                     Buffer = &Patterns[(((PatternOrder[ModPattern] << 6) + ModRow) * ModChannels) + o];\r
1654                     if(Buffer->Period != 0)\r
1655                     {\r
1656                         Channels[o].Playing = 1;\r
1657                         Channels[o].OldPeriod = Channels[o].CurPeriod;\r
1658                         Channels[o].Period = Channels[o].CurPeriod = Buffer->Period;\r
1659                         Channels[o].Offset = 0;\r
1660                         Channels[o].Looping = 0;\r
1661                         Channels[o].Reminder = 0;\r
1662                         Channels[o].Effect = 0;\r
1663                         Channels[o].EffectData.b = 0;\r
1664                     }\r
1665                     if(Buffer->Sample != 0)\r
1666                     {\r
1667                         if((Samples[Buffer->Sample - 1].SampleLen > 0) && (Samples[Buffer->Sample - 1].Volume > 0))\r
1668                         {\r
1669                             Channels[o].Playing = 1;\r
1670                             Channels[o].Sample = Buffer->Sample - 1;\r
1671                             Channels[o].Volume = Channels[o].CurVolume = Samples[Buffer->Sample - 1].Volume;\r
1672                             Channels[o].Offset = 0;\r
1673                             Channels[o].Looping = 0;\r
1674                             Channels[o].Reminder = 0;\r
1675                             Channels[o].Effect = 0;\r
1676                             Channels[o].EffectData.b = 0;\r
1677                         } else {\r
1678                             Channels[o].Playing = 0;\r
1679                         }\r
1680                     }\r
1681                     Channels[o].Effect = Buffer->Effect;\r
1682                     Channels[o].EffectData.b = Buffer->EffectData;\r
1683                     if(Buffer->Effect == 4)\r
1684                     {\r
1685                         Channels[o].Oscillation = 1;\r
1686                         if((Channels[o].EffectData.Nibbles.n1 != 0) && (Channels[o].EffectData.Nibbles.n2 != 0))\r
1687                         {\r
1688                             Channels[o].OscFreq = Channels[o].EffectData.Nibbles.n1;\r
1689                             Channels[o].OscAmp = Channels[o].EffectData.Nibbles.n2;\r
1690                         }\r
1691                         if(Channels[o].OscNoTrig == 0)\r
1692                             Channels[o].OscOffset = 0;\r
1693                     } else {\r
1694                         if((Buffer->Effect != 7) && (Buffer->Effect != 6))\r
1695                             Channels[o].Oscillation = 0;\r
1696                     }\r
1697                     if(Buffer->Effect == 7)\r
1698                     {\r
1699                         Channels[o].Oscillation = 2;\r
1700                         if((Channels[o].EffectData.Nibbles.n1 != 0) && (Channels[o].EffectData.Nibbles.n2 != 0))\r
1701                         {\r
1702                             Channels[o].OscFreq = Channels[o].EffectData.Nibbles.n1;\r
1703                             Channels[o].OscAmp = Channels[o].EffectData.Nibbles.n2;\r
1704                         }\r
1705                         if(Channels[o].OscNoTrig == 0)\r
1706                             Channels[o].OscOffset = 0;\r
1707                     } else {\r
1708                         if((Buffer->Effect != 4) && (Buffer->Effect != 6))\r
1709                             Channels[o].Oscillation = 0;\r
1710                     }\r
1711                     if(Buffer->Effect == 6)\r
1712                         Channels[o].Effect = 10;\r
1713                     if(Buffer->Effect == 9)\r
1714                         Channels[o].Offset = Buffer->EffectData << 8;\r
1715                     if(Buffer->Effect == 12)\r
1716                     {\r
1717                         Channels[o].Volume = Buffer->EffectData;\r
1718                         if(Channels[o].Volume > 64)\r
1719                             Channels[o].Volume = 64;\r
1720                         Channels[o].CurVolume = Channels[o].Volume;\r
1721                     }\r
1722                     if(Buffer->Effect == 14)\r
1723                     {\r
1724                         if((Channels[o].EffectData.Nibbles.n1 = 4) || (Channels[o].EffectData.Nibbles.n1 = 7))\r
1725                         {\r
1726                             Channels[o].OscWave = Channels[o].EffectData.Nibbles.n2 & 3;\r
1727                             Channels[o].OscOffset = 0;\r
1728                             if(Channels[o].OscWave == 3)\r
1729                                 Channels[o].OscWave = rand() % 3;\r
1730                             if(Channels[o].EffectData.Nibbles.n2 > 3)\r
1731                                 Channels[o].OscNoTrig = 1;\r
1732                             else\r
1733                                 Channels[o].OscNoTrig = 0;\r
1734                         }\r
1735                     }\r
1736                     if(Buffer->Effect == 15)\r
1737                     {\r
1738                         if(Buffer->EffectData <= 32)\r
1739                             ModTPD = Buffer->EffectData;\r
1740                         else\r
1741                             ModBPM = Buffer->EffectData;\r
1742                         ModBPD = ((5 * SBSampleRate) * ModTPD) / (ModBPM * 2);\r
1743                     }\r
1744                 }\r
1745                 if(Channels[o].Playing != 0)\r
1746                 {\r
1747                     SampleRate = 7093789 / (Channels[o].CurPeriod << 1);\r
1748                     if(KeyTable[6] == 1)\r
1749                         SampleRate <<= 1;\r
1750                     Channels[o].Reminder += SampleRate;\r
1751                     if(Channels[o].Reminder >= SBSampleRate)\r
1752                     {\r
1753                         Channels[o].LastSample = Samples[Channels[o].Sample].Buffer[Channels[o].Offset];\r
1754                         while(Channels[o].Reminder >= SBSampleRate)\r
1755                         {\r
1756                             Channels[o].Reminder -= SBSampleRate;\r
1757                             Channels[o].Offset++;\r
1758                         }\r
1759                     }\r
1760                     if(Channels[o].Looping != 0)\r
1761                     {\r
1762                         if(Channels[o].Offset >= Samples[Channels[o].Sample].LoopStart + Samples[Channels[o].Sample].LoopLen)\r
1763                             Channels[o].Offset = Samples[Channels[o].Sample].LoopStart;\r
1764                     } else {\r
1765                         if(Channels[o].Offset >= Samples[Channels[o].Sample].SampleLen)\r
1766                         {\r
1767                             if(Samples[Channels[o].Sample].LoopLen > 2)\r
1768                             {\r
1769                                 Channels[o].Looping = 1;\r
1770                                 Channels[o].Offset = Samples[Channels[o].Sample].LoopStart;\r
1771                             } else {\r
1772                                 Channels[o].Playing = 0;\r
1773                             }\r
1774                         }\r
1775                     }\r
1776                 }\r
1777                 if(Channels[o].Playing != 0)\r
1778                 {\r
1779                     Data = (signed short)Samples[Channels[o].Sample].Buffer[Channels[o].Offset];\r
1780                     Data2 += (Data * Channels[o].CurVolume) / 256;\r
1781                     if(Channels[o].Oscillation == 1)\r
1782                     {\r
1783                         Amp = (WaveForms[Channels[o].OscWave][(unsigned short)Channels[o].OscOffset] * (float)Channels[o].OscAmp) / 32;\r
1784                         Channels[o].CurPeriod = (unsigned short)((double)Channels[o].Period * pow(2, (double)(Amp / 12)));\r
1785                         Channels[o].OscOffset += ((float)Channels[o].OscFreq * (float)ModTPD * 360) / (64 * ModBPD);\r
1786                         if(Channels[o].OscOffset >= 360)\r
1787                             Channels[o].OscOffset -= 360;\r
1788                     }\r
1789                     if(Channels[o].Oscillation == 2)\r
1790                     {\r
1791                         Amp = WaveForms[Channels[o].OscWave][(unsigned short)Channels[o].OscOffset] * (float)Channels[o].OscAmp * (float)(ModTPD - 1);\r
1792                         Channels[o].CurVolume = (unsigned char)((signed char)Channels[o].Volume + (signed char)Amp);\r
1793                         if((Amp > 0) && (Channels[o].CurVolume > 64))\r
1794                             Channels[o].CurVolume = 64;\r
1795                         if((Amp < 0) && (Channels[o].CurVolume > 64))\r
1796                             Channels[o].CurVolume = 0;\r
1797                         Channels[o].OscOffset += ((float)Channels[o].OscFreq * (float)ModTPD * 360) / (64 * ModBPD);\r
1798                         if(Channels[o].OscOffset >= 360)\r
1799                             Channels[o].OscOffset -= 360;\r
1800                     }\r
1801                     if(Channels[o].Effect == 0)\r
1802                     {\r
1803                         if(ModOffset == (unsigned short)(ModBPD / 3))\r
1804                             Channels[o].CurPeriod = (unsigned short)((double)Channels[o].Period * pow(2, (double)Channels[o].EffectData.Nibbles.n1 / 12));\r
1805                         if(ModOffset == (unsigned short)((2 * ModBPD) / 3))\r
1806                             Channels[o].CurPeriod = (unsigned short)((double)Channels[o].Period * pow(2, (double)Channels[o].EffectData.Nibbles.n2 / 12));\r
1807                     }\r
1808                     if(Channels[o].Effect == 1)\r
1809                     {\r
1810                         Channels[o].CurPeriod = Channels[o].Period - (unsigned short)(((unsigned long)Channels[o].EffectData.b * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
1811                         if((signed short)Channels[o].CurPeriod < 113)\r
1812                             Channels[o].CurPeriod = 113;\r
1813                     }\r
1814                     if(Channels[o].Effect == 2)\r
1815                     {\r
1816                         Channels[o].CurPeriod = Channels[o].Period + (unsigned short)(((unsigned long)Channels[o].EffectData.b * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
1817                         if(Channels[o].CurPeriod > 856)\r
1818                             Channels[o].CurPeriod = 856;\r
1819                     }\r
1820                     if(Channels[o].Effect == 3)\r
1821                     {\r
1822                         if(Channels[o].OldPeriod > Channels[o].Period)\r
1823                         {\r
1824                             Channels[o].CurPeriod = Channels[o].OldPeriod - (unsigned short)(((unsigned long)Channels[o].EffectData.b * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
1825                             if((signed short)Channels[o].CurPeriod < Channels[o].Period)\r
1826                                 Channels[o].CurPeriod = Channels[o].Period;\r
1827                         } else {\r
1828                             Channels[o].CurPeriod = Channels[o].OldPeriod + (unsigned short)(((unsigned long)Channels[o].EffectData.b * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
1829                             if(Channels[o].CurPeriod > Channels[o].Period)\r
1830                                 Channels[o].CurPeriod = Channels[o].Period;\r
1831                         }\r
1832                     }\r
1833                     if((Channels[o].Effect == 10) && (Channels[o].EffectData.Nibbles.n1 > 0))\r
1834                     {\r
1835                         Channels[o].CurVolume = Channels[o].Volume + (unsigned char)(((unsigned long)Channels[o].EffectData.Nibbles.n1 * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
1836                         if(Channels[o].CurVolume > 64)\r
1837                             Channels[o].CurVolume = 64;\r
1838                     } else {\r
1839                         if((Channels[o].Effect == 10) && (Channels[o].EffectData.Nibbles.n2 > 0))\r
1840                         {\r
1841                             Channels[o].CurVolume = Channels[o].Volume - (unsigned char)(((unsigned long)Channels[o].EffectData.Nibbles.n2 * (unsigned long)ModTPD * (unsigned long)ModOffset) / (unsigned long)ModBPD);\r
1842                             if(Channels[o].CurVolume > 64)\r
1843                                 Channels[o].CurVolume = 0;\r
1844                         }\r
1845                     }\r
1846                 }\r
1847             }\r
1848             if(++ModOffset >= ModBPD)\r
1849             {\r
1850                 ModRow++;\r
1851                 Temp = 0;\r
1852                 for(o = 0; o < ModChannels; o++)\r
1853                 {\r
1854                     if(Channels[o].Effect == 11)\r
1855                     {\r
1856                         ModRow = 0;\r
1857                         ModPattern = Channels[o].EffectData.b;\r
1858                     }\r
1859                     if((Channels[o].Effect == 13) && (Temp == 0))\r
1860                     {\r
1861                         if(++ModPattern >= ModLen)\r
1862                         {\r
1863                             if(ModRepeat >= ModLen)\r
1864                                 ModPattern = 0;\r
1865                             else\r
1866                                 ModPattern = ModRepeat;\r
1867                         }\r
1868                         ModRow = (Channels[o].EffectData.Nibbles.n1 * 10) + Channels[o].EffectData.Nibbles.n2;\r
1869                         Temp = 1;\r
1870                     }\r
1871                 }\r
1872                 ModOffset = 0;\r
1873                 if(ModRow >= 64)\r
1874                 {\r
1875                     ModRow = 0;\r
1876                     if(++ModPattern >= ModLen)\r
1877                     {\r
1878                         if(ModRepeat >= ModLen)\r
1879                             ModPattern = 0;\r
1880                         else\r
1881                             ModPattern = ModRepeat;\r
1882                     }\r
1883                 }\r
1884             }\r
1885             Data = (signed short)SoundBuffer[i] - 128;\r
1886             Data += Data2;\r
1887             if(Data > 127)\r
1888                 Data = 127;\r
1889             if(Data < -128)\r
1890                 Data = -128;\r
1891             SoundBuffer[i] = (unsigned char)(Data + 128);\r
1892         }\r
1893     }\r
1894     BufferReady = 0;\r
1895 }\r
1896 \r
1897 unsigned long GetString(unsigned short StringNum, unsigned short *Length)\r
1898 {\r
1899     unsigned long Offset, Offset2;\r
1900     unsigned short Count;\r
1901 \r
1902     Offset = 0;\r
1903     Count = 0;\r
1904     while(Count < StringNum)\r
1905     {\r
1906         if(Strings[Offset++] == 0)\r
1907             Count++;\r
1908     }\r
1909     Offset2 = Offset;\r
1910     while(Strings[Offset2++] != 0);\r
1911     if(Length != NULL)\r
1912         *Length = Offset2 - Offset;\r
1913     return(Offset);\r
1914 }\r
1915 \r
1916 void LoadMenu(unsigned short MenuNum)\r
1917 {\r
1918     unsigned long Offset;\r
1919     unsigned short i, o;\r
1920     unsigned short NumItems, CurItem;\r
1921     unsigned char DataLength;\r
1922 \r
1923     Offset = 0;\r
1924     CurItem = 0;\r
1925     MenuID = MenuNum;\r
1926     for(i = 0; i <= MenuNum; i++)\r
1927     {\r
1928         NumItems = *(unsigned short *)(MenuBuffer + Offset);\r
1929         Offset += 2;\r
1930         if(i == MenuNum)\r
1931             NumMenuItems = NumItems;\r
1932         for(o = 0; o < NumItems; o++)\r
1933         {\r
1934             DataLength = MenuBuffer[Offset++];\r
1935             if(i == MenuNum)\r
1936             {\r
1937                 MenuItems[0][CurItem] = MenuBuffer + Offset;\r
1938                 Offset += DataLength;\r
1939                 strcpy(MenuItems[1][CurItem++], Strings + GetString(*(unsigned short *)(MenuBuffer + Offset - 2), NULL));\r
1940             } else {\r
1941                 Offset += DataLength;\r
1942             }\r
1943         }\r
1944     }\r
1945 }\r
1946 \r
1947 void LoadLayout(unsigned char NumPlayers)\r
1948 {\r
1949     unsigned char i;\r
1950     unsigned short o, Buffer[18];\r
1951     KvidFile LayoutFile;\r
1952 \r
1953     for(i = 0; i < MAX_PLAYERS; i++)\r
1954         Players[i]->Visual = 0;\r
1955     if(OpenFile("Layouts", &LayoutFile) == 0)\r
1956         return;\r
1957     for(i = 0; i < NumPlayers - 1; i++)\r
1958     {\r
1959         FileSkip(&LayoutFile, 36 * (i + 1));\r
1960     }\r
1961     for(i = 0; i < NumPlayers; i++)\r
1962     {\r
1963         FileRead((void *)&Buffer, 36, &LayoutFile);\r
1964         Players[i]->Visual = 1;\r
1965         Players[i]->VPointX1 = Buffer[0];\r
1966         Players[i]->VPointY1 = Buffer[1];\r
1967         Players[i]->VPointX2 = Buffer[2];\r
1968         Players[i]->VPointY2 = Buffer[3];\r
1969         Players[i]->AMeterX1 = Buffer[4];\r
1970         Players[i]->AMeterY1 = Buffer[5];\r
1971         Players[i]->AMeterX2 = Buffer[6];\r
1972         Players[i]->AMeterY2 = Buffer[7];\r
1973         Players[i]->LMeterX1 = Buffer[8];\r
1974         Players[i]->LMeterY1 = Buffer[9];\r
1975         Players[i]->LMeterX2 = Buffer[10];\r
1976         Players[i]->LMeterY2 = Buffer[11];\r
1977         Players[i]->lx = Buffer[12];\r
1978         Players[i]->ly = Buffer[13];\r
1979         Players[i]->kx = Buffer[14];\r
1980         Players[i]->ky = Buffer[15];\r
1981         Players[i]->cx = Buffer[16];\r
1982         Players[i]->cy = Buffer[17];\r
1983         for(o = 0; o < NUM_MASKS; o++)\r
1984         {\r
1985             if(Players[i]->Masks[o].Buffer != NULL)\r
1986                 free(Players[i]->Masks[o].Buffer);\r
1987             Players[i]->Masks[o].Buffer = (unsigned char *)malloc((Buffer[2] - Buffer[0] + 1) * (Buffer[3] - Buffer[1] + 1) * 4);\r
1988         }\r
1989     }\r
1990     FileClose(&LayoutFile);\r
1991 }\r
1992 \r
1993 unsigned char InitVar(void)\r
1994 {\r
1995     unsigned short i, o;\r
1996     KvidFile KeyFile;\r
1997 \r
1998     LoadLayout(2);\r
1999     for(i = 0; i < MAX_PLAYERS; i++)\r
2000     {\r
2001         if(i == 0)\r
2002         {\r
2003             if(OpenFile("player1.ctr", &KeyFile) == 0)\r
2004                 return(1);\r
2005         }\r
2006         if(i == 1)\r
2007         {\r
2008             if(OpenFile("player2.ctr", &KeyFile) == 0)\r
2009                 return(1);\r
2010         }\r
2011         if(i < 2)\r
2012         {\r
2013             for(o = 0; o < 9; o++)\r
2014                 FileRead((void *)&Players[i]->KeyCodes[o], 2, &KeyFile);\r
2015             FileClose(&KeyFile);\r
2016         }\r
2017         Players[i]->Angle = 0;\r
2018         Players[i]->AngleVel = 0;\r
2019         Players[i]->Dir = 0;\r
2020         Players[i]->MaxHealth = 500;\r
2021         Players[i]->Health = Players[0]->MaxHealth;\r
2022         Players[i]->Kills = 0;\r
2023         Players[i]->Lives = 5;\r
2024         Players[i]->CurWeapon = 0;\r
2025         /*Players[i]->Masks[0].Method = 1;\r
2026         Players[i]->Masks[0].Effects[0] = 2;*/\r
2027         for(o = 0; o < NUM_WEAPONS; o++)\r
2028         {\r
2029             PWeapons[i][o]->Weapon = o;\r
2030             PWeapons[i][o]->Used = 1;\r
2031         }\r
2032     }\r
2033     for(i = 0; i < MAX_PLAYERS; i++)\r
2034     {\r
2035         for(o = 0; o < NUM_WEAPONS; o++)\r
2036         {\r
2037             if((Players[i]->Used == 1) && (PWeapons[i][o]->Used == 1))\r
2038             {\r
2039                 PWeapons[i][o]->AmmoLeft = Weapons[PWeapons[i][o]->Weapon]->Ammo;\r
2040                 PWeapons[i][o]->FireTimer = 0;\r
2041                 PWeapons[i][o]->ReloadTimer = 0;\r
2042                 PWeapons[i][o]->NumClips = Weapons[PWeapons[i][o]->Weapon]->MaxClips;\r
2043             }\r
2044         }\r
2045     }\r
2046     BGSprite = 53;\r
2047     BGFrame = 0;\r
2048     FogSprite = 48;\r
2049     FogX = 0;\r
2050     FogY = 0;\r
2051     return(0);\r
2052 }\r
2053 \r
2054 unsigned char Init(unsigned short *Result)\r
2055 {\r
2056     unsigned short i, o;\r
2057     unsigned char Buffer[80], InpBuffer, BufferPos, Finished, Major, Minor;\r
2058     unsigned long LastPos, Offset, Size, u, BkAU;\r
2059     unsigned short DataLength, Count, BkOffset;\r
2060     KvidFile OpenedFile, OpenedFile2;\r
2061     KvidFile SoundFile;\r
2062 \r
2063     printf("Initializing...\n");\r
2064     MainDat = NULL;\r
2065     if((OpenDatFile("kvid.dat", &DataFile) == 0) || (DataFile.CanWrite == 0))\r
2066         return(3);\r
2067     MainDat = &DataFile;\r
2068     if(DebugMode != 0)\r
2069         printf("Initializing double buffer...\n");\r
2070     DBSetClip(0, 0, 319, 199);\r
2071     if(DebugMode != 0)\r
2072         printf("Initializing level...\n");\r
2073     MaxLW = 3200;\r
2074     MaxLH = 2000;\r
2075     for(i = 0; i < NUM_PLANES; i++)\r
2076     {\r
2077         if((LevelBuffer[i] = (unsigned char *)malloc(MaxLW * MaxLH * ((i == 0)?4:1))) == NULL)\r
2078             return(2);\r
2079     }\r
2080     if(DebugMode != 0)\r
2081         printf("Initializing variables...\n");\r
2082     for(i = 0; i < MAX_HITTESTS; i++)\r
2083     {\r
2084         HitTests[i] = 0xFFFF;\r
2085     }\r
2086     for(i = 0; i < MAX_PIXELS; i++)\r
2087     {\r
2088         if((Pixels[i] = (Pixel *)malloc(sizeof(Pixel))) == NULL)\r
2089             return(2);\r
2090         Pixels[i]->Used = 0;\r
2091     }\r
2092     for(i = 0; i < MAX_SPRITES; i++)\r
2093     {\r
2094         if((Sprites[i] = (Sprite *)malloc(sizeof(Sprite))) == NULL)\r
2095             return(2);\r
2096         Sprites[i]->Used = 0;\r
2097     }\r
2098     for(i = 0; i < MAX_OBJECTS; i++)\r
2099     {\r
2100         if((Objects[i] = (Object *)malloc(sizeof(Object))) == NULL)\r
2101             return(2);\r
2102         Objects[i]->Used = 0;\r
2103     }\r
2104     for(i = 0; i < MAX_OBJLISTS; i++)\r
2105     {\r
2106         if((ObjectLists[i] = (ObjectList *)malloc(sizeof(ObjectList))) == NULL)\r
2107             return(2);\r
2108         ObjectLists[i]->Used = 0;\r
2109     }\r
2110     for(i = 0; i < MAX_PLAYERS; i++)\r
2111     {\r
2112         if((Players[i] = (Player *)malloc(sizeof(Player))) == NULL)\r
2113             return(2);\r
2114         Players[i]->Used = 0;\r
2115         Players[i]->Visual = 0;\r
2116         for(o = 0; o < NUM_MASKS; o++)\r
2117         {\r
2118             Players[i]->Masks[o].Buffer = NULL;\r
2119             Players[i]->Masks[o].Method = 0;\r
2120             for(u = 0; u < 16; u++)\r
2121                 Players[i]->Masks[o].Effects[u] = 0;\r
2122         }\r
2123     }\r
2124     for(i = 0; i < MAX_PLAYERS; i++)\r
2125     {\r
2126         for(o = 0; o < NUM_WEAPONS; o++)\r
2127         {\r
2128             if((PWeapons[i][o] = (PWeapon *)malloc(sizeof(PWeapon))) == NULL)\r
2129                 return(2);\r
2130             PWeapons[i][o]->Used = 0;\r
2131         }\r
2132     }\r
2133     for(i = 0; i < MAX_LINES; i++)\r
2134     {\r
2135         if((Lines[i] = (Line *)malloc(sizeof(Line))) == NULL)\r
2136             return(2);\r
2137         Lines[i]->Used = 0;\r
2138     }\r
2139     for(i = 0; i < MAX_RASTERS; i++)\r
2140     {\r
2141         if((Rasters[i] = (Raster *)malloc(sizeof(Raster))) == NULL)\r
2142             return(2);\r
2143         Rasters[i]->Used = 0;\r
2144     }\r
2145     for(i = 0; i < MAX_MENUITEMS; i++)\r
2146     {\r
2147         if((MenuItems[1][i] = (unsigned char *)malloc(128)) == NULL)\r
2148             return(2);\r
2149     }\r
2150     for(i = 0; i < MAX_SOUNDS; i++)\r
2151     {\r
2152         Sounds[i].Playing = 0;\r
2153     }\r
2154     if((MenuBuffer = (unsigned char *)malloc(16384)) == NULL)\r
2155         return(2);\r
2156     if((TextBuffer = (unsigned char *)malloc(500)) == NULL)\r
2157         return(2);\r
2158     if((KeyboardBuffer = (unsigned char *)malloc(500)) == NULL)\r
2159         return(2);\r
2160     if((LevelFileName = (unsigned char *)malloc(100)) == NULL)\r
2161         return(2);\r
2162     if((Patterns = (ModEvent *)malloc(MAX_PATTERNS * 512 * sizeof(ModEvent))) == NULL)\r
2163         return(2);\r
2164     if((SoundBuffer = (unsigned char *)malloc(SB_SIZE >> 1)) == NULL)\r
2165         return(2);\r
2166     for(i = 0; i < SB_SIZE >> 1; i++)\r
2167         SoundBuffer[i] = 128;\r
2168     TransOps[0] = ColorAdd;\r
2169     TransOps[1] = ColorSub;\r
2170     TransOps[2] = ColorAvr;\r
2171     TransOps[3] = ColorSpc;\r
2172     TransOps[4] = ColorFul;\r
2173     Gravity = 0.02;\r
2174     LevelWidth = 640;\r
2175     LevelHeight = 400;\r
2176     FrameRate = 50;\r
2177     DSPAddress = 0x220;\r
2178     DMAChannel = 1;\r
2179     IRQLine = 5;\r
2180     ModPlaying = 0;\r
2181     MenuActive = 0;\r
2182     EmptyKeyBuffer();\r
2183     srand((unsigned int)time(NULL));\r
2184     for(i = 0; i < 360; i++)\r
2185     {\r
2186         Sine[i] = sin(((float)i / 180) * M_PI);\r
2187         Cosine[i] = cos(((float)i / 180) * M_PI);\r
2188         PreSine[i] = sin(((double)i / 90) * M_PI_2);\r
2189         PreCosine[i] = cos(((double)i / 90) * M_PI_2);\r
2190         WaveForms[0][i] = sin(((float)i / 180) * M_PI);\r
2191         WaveForms[1][i] = (float)(359 - i) / 359;\r
2192         WaveForms[2][i] = (i < 180)?1:0;\r
2193         WaveForms[3][i] = (float)i / 359;\r
2194         WaveForms[4][i] = (i < 180)?((float)i / 179):((float)(179 - (i - 180)) / 179);\r
2195     }\r
2196     for(i = 0; i < MAX_SAMPLES; i++)\r
2197     {\r
2198         Samples[i].Allocated = 0;\r
2199     }\r
2200     if(DebugMode != 0)\r
2201         printf("Loading data...\n");\r
2202     if(OpenFile("Layouts", &OpenedFile) == 0)\r
2203         return(4);\r
2204     FileClose(&OpenedFile);\r
2205     if(DebugMode != 0)\r
2206         printf("Loading menus\n");\r
2207     if(OpenFile("MenuData", &OpenedFile) == 0)\r
2208         return(4);\r
2209     FileRead((void *)&Count, 2, &OpenedFile);\r
2210     Offset = 0;\r
2211     for(i = 0; i < Count; i++)\r
2212     {\r
2213         FileRead((void *)&DataLength, 2, &OpenedFile);\r
2214         *(unsigned short *)(MenuBuffer + Offset) = DataLength;\r
2215         Offset += 2;\r
2216         for(o = 0; o < DataLength; o++)\r
2217         {\r
2218             FileRead((void *)&InpBuffer, 1, &OpenedFile);\r
2219             MenuBuffer[Offset++] = InpBuffer;\r
2220             FileRead((void *)(MenuBuffer + Offset), (unsigned long)InpBuffer, &OpenedFile);\r
2221             Offset += InpBuffer;\r
2222         }\r
2223     }\r
2224     FileClose(&OpenedFile);\r
2225     if(DebugMode != 0)\r
2226         printf("Loading palette...\n");\r
2227     if(OpenFile("DefaultPalette", &OpenedFile) == 0)\r
2228         return(4);\r
2229     FileRead((void *)Palette, sizeof(Pal) * NUM_COLORS, &OpenedFile);\r
2230     FileClose(&OpenedFile);\r
2231     if(DebugMode != 0)\r
2232         printf("Loading color info...\n");\r
2233     if(OpenFile("ColorInfo", &OpenedFile) == 0)\r
2234         return(4);\r
2235     FileRead((void *)ColorInfo, NUM_COLORS, &OpenedFile);\r
2236     FileClose(&OpenedFile);\r
2237     if(DebugMode != 0)\r
2238         printf("Loading ASCII Table...\n");\r
2239     if(OpenFile("AsciiConv", &OpenedFile) == 0)\r
2240         return(4);\r
2241     FileRead((void *)AsciiTable, 512, &OpenedFile);\r
2242     FileClose(&OpenedFile);\r
2243     if(OpenFile("MainAscii", &OpenedFile) == 0)\r
2244         return(4);\r
2245     FileRead((void *)AsciiTable2, 256, &OpenedFile);\r
2246     FileClose(&OpenedFile);\r
2247     if(DebugMode != 0)\r
2248         printf("Loading strings...\n");\r
2249     if(OpenFile("Strings", &OpenedFile) == 0)\r
2250         return(4);\r
2251     FileRead((void *)&LastPos, 4, &OpenedFile);\r
2252     if((Strings = (unsigned char *)malloc((unsigned short)LastPos)) == NULL)\r
2253         return(2);\r
2254     for(Offset = 0; Offset < LastPos; Offset++)\r
2255         Strings[Offset] = FileGetChar(&OpenedFile);\r
2256     FileClose(&OpenedFile);\r
2257     if(PLAY_TIME > 0)\r
2258     {\r
2259         if((OpenFile("BetaTime", &OpenedFile) == 0) || (OpenedFile.CanWrite == 0))\r
2260             return(4);\r
2261         FileRead((void *)&Count, 2, &OpenedFile);\r
2262         if(Count != 0x464B)\r
2263             return(4);\r
2264         BkAU = OpenedFile.CurAU;\r
2265         BkOffset = OpenedFile.Offset;\r
2266         FileRead((void *)&NumPlays, 1, &OpenedFile);\r
2267         if(NumPlays == 0)\r
2268         {\r
2269             printf("Your beta version has expired!\n");\r
2270             return(4);\r
2271         }\r
2272         OpenedFile.CurAU = BkAU;\r
2273         OpenedFile.Offset = BkOffset;\r
2274         OpenedFile.ReSeek = 1;\r
2275         FilePutChar(--NumPlays, &OpenedFile);\r
2276         printf("You have %u time(s) left to play!\n", (unsigned short)NumPlays);\r
2277     }\r
2278     if(DebugMode != 0)\r
2279         printf("Loading sprites...\n");\r
2280     if(OpenFile("SpriteCache", &OpenedFile) == 0)\r
2281         return(4);\r
2282     FileRead((void *)&NumSprites, 2, &OpenedFile);\r
2283     if((Caches = (Cache **)malloc(4 * NumSprites)) == NULL)\r
2284         return(2);\r
2285     for(i = 0; i < NumSprites; i++)\r
2286     {\r
2287         if((Caches[i] = (Cache *)malloc(sizeof(Cache))) == NULL)\r
2288             return(2);\r
2289         BufferPos = 0;\r
2290         Finished = 0;\r
2291         while(Finished == 0)\r
2292         {\r
2293             InpBuffer = FileGetChar(&OpenedFile);\r
2294             if(InpBuffer == 0)\r
2295             {\r
2296                 Buffer[BufferPos] = 0;\r
2297                 OpenedFile.ReSeek = 1;\r
2298                 switch(LoadSprite((unsigned char *)Buffer, i))\r
2299                 {\r
2300                     case 1:\r
2301                         return(4);\r
2302                     case 2:\r
2303                         return(2);\r
2304                 }\r
2305                 if(strcmp((char *)Buffer, (unsigned char *)"Spr_Font") == 0)\r
2306                     FontSprite = i;\r
2307                 Finished = 1;\r
2308             } else {\r
2309                 Buffer[BufferPos++] = InpBuffer;\r
2310             }\r
2311         }\r
2312     }\r
2313     FileClose(&OpenedFile);\r
2314     if(DebugMode != 0)\r
2315         printf("Loading classes...\n");\r
2316     if(OpenFile("Classes", &OpenedFile) == 0)\r
2317         return(4);\r
2318     FileRead((void *)&NumClasses, 2, &OpenedFile);\r
2319     if((Classes = (Class **)malloc(4 * NumClasses)) == NULL)\r
2320         return(2);\r
2321     for(i = 0; i < NumClasses; i++)\r
2322     {\r
2323         if((Classes[i] = (Class *)malloc(sizeof(Class))) == NULL)\r
2324             return(2);\r
2325         FileRead((void *)&Classes[i]->Scripts, 2 * NUM_SCRIPTS, &OpenedFile);\r
2326         FileRead((void *)&Classes[i]->TickDelay, 1, &OpenedFile);\r
2327         FileRead((void *)&Classes[i]->GravityMod, 2, &OpenedFile);\r
2328         FileRead((void *)&Classes[i]->Sprite, 1, &OpenedFile);\r
2329         FileRead((void *)&Classes[i]->StartFrame, 1, &OpenedFile);\r
2330         FileRead((void *)&Classes[i]->RunHitTests, 1, &OpenedFile);\r
2331         FileRead((void *)&Classes[i]->TouchDelay, 1, &OpenedFile);\r
2332         FileRead((void *)&Classes[i]->TransSprite, 1, &OpenedFile);\r
2333         FileRead((void *)&DataLength, 2, &OpenedFile);\r
2334         if((Classes[i]->Code = (unsigned char *)malloc(DataLength)) == NULL)\r
2335             return(2);\r
2336         FileRead((void *)Classes[i]->Code, DataLength, &OpenedFile);\r
2337     }\r
2338     FileClose(&OpenedFile);\r
2339     if(DebugMode != 0)\r
2340         printf("Loading sounds...\n");\r
2341     UseSound = 1;\r
2342     FreeSound = 1;\r
2343     if(OpenDatFile("kvidsnd.dat", &SoundFile) == 0)\r
2344     {\r
2345         printf("Couldn't find sound file KVIDSND.DAT!\nUsing no sound...\n");\r
2346         UseSound = 0;\r
2347         FreeSound = 0;\r
2348     }\r
2349     if(UseSound == 1)\r
2350     {\r
2351         if(OpenNestedFile("LoadSound", &OpenedFile, &SoundFile, NULL) == 0)\r
2352         {\r
2353             printf("Sound file corrupt!\nUsing no sound...\n");\r
2354             UseSound = 0;\r
2355             FreeSound = 0;\r
2356         }\r
2357     }\r
2358     if(UseSound == 1)\r
2359     {\r
2360         FileRead((void *)&NumSounds, 2, &OpenedFile);\r
2361         if((SoundCaches = (SoundCache **)malloc(NumSounds << 2)) == NULL)\r
2362             return(2);\r
2363         for(i = 0; i < NumSounds; i++)\r
2364             SoundCaches[i] = NULL;\r
2365         BufferPos = 0;\r
2366         for(i = 0; i < NumSounds; i++)\r
2367         {\r
2368             OpenedFile.ReSeek = 1;\r
2369             for(BufferPos = 0; (Buffer[BufferPos] = FileGetChar(&OpenedFile)) != 0; BufferPos++);\r
2370             if(OpenNestedFile(Buffer, &OpenedFile2, &SoundFile, NULL) == 0)\r
2371             {\r
2372                 printf("Sound file corrupt!\nUsing no sound...\n");\r
2373                 UseSound = 0;\r
2374                 break;\r
2375             }\r
2376             Offset = 0;\r
2377             if((SoundCaches[i] = (SoundCache *)malloc(sizeof(SoundCache))) == NULL)\r
2378                 return(2);\r
2379             FileRead((void *)&Size, 4, &OpenedFile2);\r
2380             SoundCaches[i]->Length = Size;\r
2381             if((SoundCaches[i]->SoundBuffer = (unsigned char *)malloc(Size)) == NULL)\r
2382                 return(2);\r
2383             DataLength = 0;\r
2384             for(u = 0; u <= Size; u++)\r
2385             {\r
2386                 if(DataLength > 0)\r
2387                 {\r
2388                     SoundCaches[i]->SoundBuffer[Offset++] = InpBuffer;\r
2389                     DataLength--;\r
2390                 }\r
2391                 if(DataLength == 0)\r
2392                 {\r
2393                     DataLength = 1;\r
2394                     if((InpBuffer = FileGetChar(&OpenedFile2)) >= 192)\r
2395                     {\r
2396                         DataLength = InpBuffer - 191;\r
2397                         InpBuffer = FileGetChar(&OpenedFile2);\r
2398                     }\r
2399                 }\r
2400             }\r
2401             FileClose(&OpenedFile2);\r
2402         }\r
2403         FileClose(&OpenedFile);\r
2404         FileClose(&SoundFile);\r
2405     }\r
2406     if(OpenFile("WeaponInfo", &OpenedFile) == 0)\r
2407         return(4);\r
2408     FileRead((void *)&NumWeapons, 2, &OpenedFile);\r
2409     if((Weapons = (Weapon **)malloc(4 * NumWeapons)) == NULL)\r
2410         return(2);\r
2411     for(i = 0; i < NumWeapons; i++)\r
2412     {\r
2413         if((Weapons[i] = (Weapon *)malloc(sizeof(Weapon))) == NULL)\r
2414             return(2);\r
2415         FileRead((void *)&Weapons[i]->Class, 2, &OpenedFile);\r
2416         FileRead((void *)&Weapons[i]->ReloadDelay, 2, &OpenedFile);\r
2417         FileRead((void *)&Weapons[i]->FireDelay, 2, &OpenedFile);\r
2418         FileRead((void *)&Weapons[i]->Ammo, 2, &OpenedFile);\r
2419         FileRead((void *)&Weapons[i]->MaxClips, 2, &OpenedFile);\r
2420         Weapons[i]->Name = 0;\r
2421         FileRead((void *)&Weapons[i]->Name, 2, &OpenedFile);\r
2422         Weapons[i]->Name = GetString((unsigned short)Weapons[i]->Name, (unsigned short *)&Weapons[i]->NameLength);\r
2423     }\r
2424     FileClose(&OpenedFile);\r
2425     if(OpenFile("MainFont", &OpenedFile) == 0)\r
2426         return(4);\r
2427     if((FontBuffer = (unsigned short *)malloc(16384)) == NULL)\r
2428         return(2);\r
2429     memset((void *)FontBuffer, 0, 16384);\r
2430     Offset = 0;\r
2431     Size = 1;\r
2432     for(i = 0; (i < 256) && (Size != 0); i++)\r
2433     {\r
2434         Size = 0;\r
2435         FileRead((void *)&Size, 2, &OpenedFile);\r
2436         FontBuffer[(i << 1)] = (unsigned short)Offset;\r
2437         FontBuffer[(i << 1) + 1] = (unsigned short)Size;\r
2438         for(o = 0; o < Size * 5; o++)\r
2439         {\r
2440             FileRead((void *)&FontBuffer[Offset + 512], 4, &OpenedFile);\r
2441             Offset += 2;\r
2442         }\r
2443     }\r
2444     FileClose(&OpenedFile);\r
2445     if(DebugMode != 0)\r
2446         printf("Initializing hardware...\n");\r
2447     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0)\r
2448     {\r
2449         printf("%s\n", SDL_GetError());\r
2450         return(0);\r
2451     }\r
2452     if((UseSound == 1) && (SBReset() != 0))\r
2453     {\r
2454         printf("Sound Blaster hardware reset failed!\n");\r
2455         UseSound = 0;\r
2456     }\r
2457     if(UseSound == 1)\r
2458     {\r
2459         SBSampleRate = 44100;\r
2460     } else {\r
2461         printf("Using no sound...\n");\r
2462     }\r
2463     VBuffer = SDL_SetVideoMode(320, 200, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);\r
2464     BPP = VBuffer->format->BytesPerPixel * 8;\r
2465     if(BPP != 32)\r
2466     {\r
2467         printf("Video mode format mismatch (BPP = %i)\n", BPP);\r
2468         return(1);\r
2469     }\r
2470     DblBuffer = VBuffer->pixels;\r
2471     FullScreen = 0;\r
2472     printf("Done!\n");\r
2473 /*  getch(); */\r
2474     SetMode(1);\r
2475     if(UseSound == 1)\r
2476     {\r
2477         ReadyBuffer = 0;\r
2478         BufferReady = 0;\r
2479         FillBuffer();\r
2480         ReadyBuffer = 1;\r
2481         StartPlayBack();\r
2482     }\r
2483     return(0xFF);\r
2484 }\r
2485 \r
2486 void Terminate(void)\r
2487 {\r
2488     unsigned short i, o;\r
2489 \r
2490     SetMode(0);\r
2491     SDL_Quit();\r
2492     FileClose(&DataFile);\r
2493     MainDat = NULL;\r
2494     for(i = 0; i < NUM_PLANES; i++)\r
2495         free(LevelBuffer[i]);\r
2496     if(FontBuffer != NULL)\r
2497         free(FontBuffer);\r
2498     if(FreeSound == 1)\r
2499     {\r
2500         for(i = 0; i < NumSounds; i++)\r
2501         {\r
2502             if(SoundCaches[i] != NULL)\r
2503             {\r
2504                 free(SoundCaches[i]->SoundBuffer);\r
2505                 free(SoundCaches[i]);\r
2506             }\r
2507         }\r
2508         free(SoundCaches);\r
2509     }\r
2510     if(UseSound == 1)\r
2511         TerminatePlayBack();\r
2512     for(i = 0; i < MAX_PIXELS; i++)\r
2513     {\r
2514         if(Pixels[i] != NULL)\r
2515             free(Pixels[i]);\r
2516     }\r
2517     for(i = 0; i < NumSprites; i++)\r
2518     {\r
2519         if(Caches[i] != NULL)\r
2520         {\r
2521             if(Caches[i]->cx != NULL)\r
2522                 free(Caches[i]->cx);\r
2523             if(Caches[i]->cy != NULL)\r
2524                 free(Caches[i]->cy);\r
2525             if(Caches[i]->Frames != NULL)\r
2526             {\r
2527                 for(o = 0; o < Caches[i]->NumFrames; o++)\r
2528                 {\r
2529                     if(Caches[i]->Frames[o] != NULL)\r
2530                         free(Caches[i]->Frames[o]);\r
2531                 }\r
2532                 free(Caches[i]->Frames);\r
2533             }\r
2534             free(Caches[i]);\r
2535         }\r
2536     }\r
2537     if(Caches != NULL)\r
2538         free(Caches);\r
2539     for(i = 0; i < MAX_SPRITES; i++)\r
2540     {\r
2541         if(Sprites[i] != NULL)\r
2542             free(Sprites[i]);\r
2543     }\r
2544     for(i = 0; i < MAX_PLAYERS; i++)\r
2545     {\r
2546         if(Players[i] != NULL)\r
2547         {\r
2548             for(o = 0; o < NUM_MASKS; o++)\r
2549             {\r
2550                 if(Players[i]->Masks[o].Buffer != NULL)\r
2551                     free(Players[i]->Masks[o].Buffer);\r
2552             }\r
2553             free(Players[i]);\r
2554         }\r
2555     }\r
2556     for(i = 0; i < MAX_OBJECTS; i++)\r
2557     {\r
2558         if(Objects[i] != NULL)\r
2559             free(Objects[i]);\r
2560     }\r
2561     for(i = 0; i < NumClasses; i++)\r
2562     {\r
2563         if(Classes[i]->Code != NULL)\r
2564             free(Classes[i]->Code);\r
2565         if(Classes[i] != NULL)\r
2566             free(Classes[i]);\r
2567     }\r
2568     if(Classes != NULL)\r
2569         free(Classes);\r
2570     for(i = 0; i < NumWeapons; i++)\r
2571     {\r
2572         if(Weapons[i] != NULL)\r
2573             free(Weapons[i]);\r
2574     }\r
2575     if(Weapons != NULL)\r
2576         free(Weapons);\r
2577     for(i = 0; i < MAX_PLAYERS; i++)\r
2578     {\r
2579         for(o = 0; o < NUM_WEAPONS; o++)\r
2580         {\r
2581             if(PWeapons[i][o] != NULL)\r
2582                 free(PWeapons[i][o]);\r
2583         }\r
2584     }\r
2585     for(i = 0; i < MAX_LINES; i++)\r
2586     {\r
2587         if(Lines[i] != NULL)\r
2588             free(Lines[i]);\r
2589     }\r
2590     for(i = 0; i < MAX_RASTERS; i++)\r
2591     {\r
2592         if(Rasters[i] != NULL)\r
2593             free(Rasters[i]);\r
2594     }\r
2595     for(i = 0; i < MAX_MENUITEMS; i++)\r
2596     {\r
2597         if(MenuItems[1][i] != NULL)\r
2598             free(MenuItems[1][i]);\r
2599     }\r
2600     if(Strings != NULL)\r
2601         free(Strings);\r
2602     if(MenuBuffer != NULL)\r
2603         free(MenuBuffer);\r
2604     if(TextBuffer != NULL)\r
2605         free(TextBuffer);\r
2606     if(KeyboardBuffer != NULL)\r
2607         free(KeyboardBuffer);\r
2608     if(LevelFileName != NULL)\r
2609         free(LevelFileName);\r
2610     if(SoundBuffer != NULL)\r
2611         free(SoundBuffer);\r
2612     if(Patterns != NULL)\r
2613         free(Patterns);\r
2614     for(i = 0; i < MAX_SAMPLES; i++)\r
2615     {\r
2616         if(Samples[i].Allocated != 0)\r
2617             free(Samples[i].Buffer);\r
2618     }\r
2619 }\r
2620 \r
2621 void HurtRadius(signed short x, signed short y, signed short StartDamage, signed short StopDamage, unsigned short StartDecRadius, unsigned short StopRadius, unsigned char Owner)\r
2622 {\r
2623     unsigned short i;\r
2624     signed long square, xdist, ydist;\r
2625     unsigned short Radius, Sprite;\r
2626     unsigned short Template;\r
2627     signed short Damage;\r
2628 \r
2629     for(i = 0; i < MAX_OBJECTS; i++)\r
2630     {\r
2631         if(Objects[i]->Used == 1)\r
2632         {\r
2633             if((Objects[i]->SpriteLink != 0xFFFF) && (Sprites[Objects[i]->SpriteLink]->Template != 0xFF))\r
2634             {\r
2635                 Sprite = Objects[i]->SpriteLink;\r
2636                 Template = (unsigned short)Sprites[Sprite]->Template;\r
2637                 xdist = (signed long)(x - (signed short)Objects[i]->x + Caches[Template]->cx[Sprites[Sprite]->CurFrame]);\r
2638                 ydist = (signed long)(y - (signed short)Objects[i]->y + Caches[Template]->cy[Sprites[Sprite]->CurFrame]);\r
2639                 if(xdist < 0) xdist = 0;\r
2640                 if(ydist < 0) ydist = 0;\r
2641                 if(xdist > (signed long)Caches[Template]->w) xdist = (signed long)Caches[Template]->w;\r
2642                 if(ydist > (signed long)Caches[Template]->h) ydist = (signed long)Caches[Template]->h;\r
2643                 xdist += (signed long)Objects[i]->x - (signed long)Caches[Template]->cx[Sprites[Sprite]->CurFrame];\r
2644                 ydist += (signed long)Objects[i]->y - (signed long)Caches[Template]->cy[Sprites[Sprite]->CurFrame];\r
2645             } else {\r
2646                 xdist = (signed long)Objects[i]->x;\r
2647                 ydist = (signed long)Objects[i]->y;\r
2648             }\r
2649             xdist = (signed long)(x - (signed short)xdist);\r
2650             ydist = (signed long)(y - (signed short)ydist);\r
2651             square = (xdist * xdist) + (ydist * ydist);\r
2652             Radius = (unsigned short)sqrt((double)square);\r
2653             if(Radius < StopRadius)\r
2654             {\r
2655                 if(Radius < StartDecRadius)\r
2656                 {\r
2657                     Damage = StartDamage;\r
2658                 } else {\r
2659                     Damage = (unsigned short)((((float)(Radius - StartDecRadius) / (float)(StopRadius - StartDecRadius)) * (float)(StartDamage - StopDamage)) + StopDamage);\r
2660                 }\r
2661                 Regs[16] = (signed short)i;\r
2662                 Regs[17] = (signed short)Damage;\r
2663                 Regs[18] = (signed short)Owner;\r
2664                 Regs[19] = (signed short)Objects[i]->x;\r
2665                 Regs[20] = (signed short)Objects[i]->y;\r
2666                 Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Objects[i]->Class]->Scripts[3]);                        //TakeDamage\r
2667             }\r
2668         }\r
2669     }\r
2670 }\r
2671 \r
2672 unsigned char SpritesOverlap(unsigned char Cache1, unsigned short Frame1, unsigned char Cache2, unsigned short Frame2, signed short dx, signed short dy)\r
2673 {\r
2674     signed short x, y;\r
2675     unsigned short w, h;\r
2676     unsigned char *Buffer1;\r
2677     unsigned char *Buffer2;\r
2678     unsigned long Offset;\r
2679     unsigned long Data;\r
2680 \r
2681     Buffer1 = Caches[Cache1]->Frames[Frame1];\r
2682     Buffer2 = Caches[Cache2]->Frames[Frame2];\r
2683     dx += Caches[Cache1]->cx[Frame1];\r
2684     dy += Caches[Cache1]->cy[Frame1];\r
2685     dx -= Caches[Cache2]->cx[Frame2];\r
2686     dy -= Caches[Cache2]->cy[Frame2];\r
2687     w = Caches[Cache2]->w;\r
2688     h = Caches[Cache2]->h;\r
2689     Offset = 0;\r
2690     y = dy;\r
2691     for(y = -dy; y < (signed short)Caches[Cache1]->h - dy; y++)\r
2692     {\r
2693         if((y < (signed short)h) && (y >= 0))\r
2694         {\r
2695             for(x = -dx; x < (signed short)Caches[Cache1]->w - dx; x++)\r
2696             {\r
2697                 if((x < (signed short)w) && (x >= 0))\r
2698                 {\r
2699                     Data = *(unsigned long *)Buffer1;\r
2700                     Buffer1 += 4;\r
2701                     if(Data != 0)\r
2702                     {\r
2703                         if(*(unsigned long *)&Buffer2[(x + (y * w)) << 2] != 0)\r
2704                             return(1);\r
2705                     }\r
2706                 } else {\r
2707                     Buffer1 += 4;\r
2708                 }\r
2709             }\r
2710         } else {\r
2711             Buffer1 += Caches[Cache1]->w << 2;\r
2712         }\r
2713     }\r
2714     return(0);\r
2715 }\r
2716 \r
2717 void __inline GetNextLineCoord(signed short *x, signed short *y, signed short *d, unsigned short dx, unsigned short dy, signed short xi, signed short yi)\r
2718 {\r
2719     if(dx > dy)\r
2720     {\r
2721         *d += dy;\r
2722         if(*d > dx)\r
2723         {\r
2724             *d -= dx;\r
2725             *y += yi;\r
2726         }\r
2727         *x += xi;\r
2728     } else {\r
2729         *d += dx;\r
2730         if(*d > 0)\r
2731         {\r
2732             *d -= dy;\r
2733             *x += xi;\r
2734         }\r
2735         *y += yi;\r
2736     }\r
2737 }\r
2738 \r
2739 unsigned short HitTest(signed short x, signed short y, unsigned short ObjNum, unsigned char TestCache, unsigned short TestFrame)\r
2740 {\r
2741     unsigned short i;\r
2742     unsigned short SpriteLink;\r
2743     unsigned char Template;\r
2744     signed short tx1, ty1, tx2, ty2;\r
2745     unsigned long Offset;\r
2746     unsigned char *FrameBuffer;\r
2747 \r
2748     for(i = 0; i < MAX_HITTESTS; i++)\r
2749     {\r
2750         if(HitTests[i] == 0xFFFF)\r
2751             break;\r
2752         if(HitTests[i] == ObjNum)\r
2753             continue;\r
2754         SpriteLink = Objects[HitTests[i]]->SpriteLink;\r
2755         if(SpriteLink != 0xFFFF)\r
2756         {\r
2757             Template = Sprites[SpriteLink]->Template;\r
2758             if(TestCache == 0xFF)\r
2759             {\r
2760                 tx1 = x;\r
2761                 ty1 = y;\r
2762                 tx2 = x;\r
2763                 ty2 = y;\r
2764             } else {\r
2765                 tx1 = x - Caches[TestCache]->cx[TestFrame];\r
2766                 ty1 = y - Caches[TestCache]->cy[TestFrame];\r
2767                 tx2 = tx1 + Caches[TestCache]->w;\r
2768                 ty2 = ty1 + Caches[TestCache]->h;\r
2769             }\r
2770             if((tx2 >= Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame]) && (ty2 >= Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) && (tx1 < Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame] + Caches[Template]->w) && (ty1 < Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame] + Caches[Template]->h))\r
2771             {\r
2772                 if(TestCache == 0xFF)\r
2773                 {\r
2774                     Offset = x - Sprites[SpriteLink]->x + Caches[Template]->cx[Sprites[SpriteLink]->CurFrame];\r
2775                     Offset += (y - Sprites[SpriteLink]->y + Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) * Caches[Template]->w;\r
2776                     FrameBuffer = Caches[Template]->Frames[Sprites[SpriteLink]->CurFrame];\r
2777                     if((Offset < Caches[Template]->w * Caches[Template]->h) && (*(unsigned long *)&FrameBuffer[Offset << 2] != 0))\r
2778                         return(HitTests[i]);\r
2779                 } else {\r
2780                     if(SpritesOverlap(TestCache, TestFrame, Template, Sprites[SpriteLink]->CurFrame, Sprites[SpriteLink]->x - x, Sprites[SpriteLink]->y - y) == 1)\r
2781                         return(HitTests[i]);\r
2782                 }\r
2783             }\r
2784         }\r
2785     }\r
2786     return(0xFFFF);\r
2787 }\r
2788 \r
2789 unsigned char CollisionTest(signed short *x1, signed short *y1, signed short *x2, signed short *y2, unsigned char Pattern, unsigned char RunHitTests, unsigned short *ObjNum, unsigned char TestCache, unsigned short TestFrame)\r
2790 {\r
2791     unsigned short i;\r
2792     signed short dx, dy, x, y, fx, fy;\r
2793     signed short xi, yi, d;\r
2794     unsigned long Data;\r
2795     unsigned char Collided;\r
2796     unsigned short Object, ObjectList, NumObjects;\r
2797 \r
2798     dx = *x2 - *x1;\r
2799     dy = *y2 - *y1;\r
2800     if(dx >= 0)\r
2801     {\r
2802         xi = 1;\r
2803     } else {\r
2804         xi = -1;\r
2805         dx = -dx;\r
2806     }\r
2807     if(dy >= 0)\r
2808     {\r
2809         yi = 1;\r
2810     } else {\r
2811         yi = -1;\r
2812         dy = -dy;\r
2813     }\r
2814     d = 0;\r
2815     x = *x1;\r
2816     y = *y1;\r
2817     Collided = 0;\r
2818     ObjectList = 0xFFFF;\r
2819     if(dx > dy)\r
2820     {\r
2821         for(i = 0; i <= dx; i++)\r
2822         {\r
2823             fx = x;\r
2824             fy = y;\r
2825             d += dy;\r
2826             if(d > dx)\r
2827             {\r
2828                 d -= dx;\r
2829                 y += yi;\r
2830             }\r
2831             x += xi;\r
2832             Data = GetMapPixel((unsigned short)x, (unsigned short)y, 1);\r
2833             if((Data & Pattern) == 0)\r
2834             {\r
2835                 *x1 = fx;\r
2836                 *y1 = fy;\r
2837                 *x2 = x;\r
2838                 *y2 = y;\r
2839                 if(Collided == 2)\r
2840                     *ObjNum = ObjectList;\r
2841                 return(1 | Collided);\r
2842             }\r
2843             if(RunHitTests != 0)\r
2844             {\r
2845                 if((Object = HitTest(x, y, *ObjNum, TestCache, TestFrame)) != 0xFFFF)\r
2846                 {\r
2847                     if(RunHitTests == 1)\r
2848                     {\r
2849                         *x1 = fx;\r
2850                         *y1 = fy;\r
2851                         *x2 = x;\r
2852                         *y2 = y;\r
2853                         *ObjNum = Object;\r
2854                         return(2);\r
2855                     } else {\r
2856                         if(ObjectList == 0xFFFF)\r
2857                         {\r
2858                             if((ObjectList = GetObjectList()) == 0xFFFF)\r
2859                             {\r
2860                                 *x1 = fx;\r
2861                                 *y1 = fy;\r
2862                                 *x2 = x;\r
2863                                 *y2 = y;\r
2864                                 *ObjNum = 0xFFFF;\r
2865                                 return(2);\r
2866                             }\r
2867                         }\r
2868                         NumObjects = ObjectLists[ObjectList]->NumObjects;\r
2869                         ObjectLists[ObjectList]->Objects[NumObjects].Object = Object;\r
2870                         ObjectLists[ObjectList]->Objects[NumObjects].x1 = fx;\r
2871                         ObjectLists[ObjectList]->Objects[NumObjects].y1 = fy;\r
2872                         ObjectLists[ObjectList]->Objects[NumObjects].x2 = x;\r
2873                         ObjectLists[ObjectList]->Objects[NumObjects].y2 = y;\r
2874                         ObjectLists[ObjectList]->Objects[NumObjects + 1].Object = 0xFFFF;\r
2875                         ObjectLists[ObjectList]->NumObjects++;\r
2876                         Collided = 2;\r
2877                     }\r
2878                 }\r
2879             }\r
2880         }\r
2881     } else {\r
2882         for(i = 0; i <= dy; i++)\r
2883         {\r
2884             fx = x;\r
2885             fy = y;\r
2886             d += dx;\r
2887             if(d > 0)\r
2888             {\r
2889                 d -= dy;\r
2890                 x += xi;\r
2891             }\r
2892             y += yi;\r
2893             Data = GetMapPixel((unsigned short)x, (unsigned short)y, 1);\r
2894             if((Data & Pattern) == 0)\r
2895             {\r
2896                 *x1 = fx;\r
2897                 *y1 = fy;\r
2898                 *x2 = x;\r
2899                 *y2 = y;\r
2900                 if(Collided == 2)\r
2901                     *ObjNum = ObjectList;\r
2902                 return(1 | Collided);\r
2903             }\r
2904             if(RunHitTests != 0)\r
2905             {\r
2906                 if((Object = HitTest(x, y, *ObjNum, TestCache, TestFrame)) != 0xFFFF)\r
2907                 {\r
2908                     if(RunHitTests == 1)\r
2909                     {\r
2910                         *x1 = fx;\r
2911                         *y1 = fy;\r
2912                         *x2 = x;\r
2913                         *y2 = y;\r
2914                         *ObjNum = Object;\r
2915                         return(2);\r
2916                     } else {\r
2917                         if(ObjectList == 0xFFFF)\r
2918                         {\r
2919                             if((ObjectList = GetObjectList()) == 0xFFFF)\r
2920                             {\r
2921                                 *x1 = fx;\r
2922                                 *y1 = fy;\r
2923                                 *x2 = x;\r
2924                                 *y2 = y;\r
2925                                 *ObjNum = 0xFFFF;\r
2926                                 return(2);\r
2927                             }\r
2928                         }\r
2929                         NumObjects = ObjectLists[ObjectList]->NumObjects;\r
2930                         ObjectLists[ObjectList]->Objects[NumObjects].Object = Object;\r
2931                         ObjectLists[ObjectList]->Objects[NumObjects].x1 = fx;\r
2932                         ObjectLists[ObjectList]->Objects[NumObjects].y1 = fy;\r
2933                         ObjectLists[ObjectList]->Objects[NumObjects].x2 = x;\r
2934                         ObjectLists[ObjectList]->Objects[NumObjects].y2 = y;\r
2935                         ObjectLists[ObjectList]->Objects[NumObjects + 1].Object = 0xFFFF;\r
2936                         ObjectLists[ObjectList]->NumObjects++;\r
2937                         Collided = 2;\r
2938                     }\r
2939                 }\r
2940             }\r
2941         }\r
2942     }\r
2943     return(Collided);\r
2944 }\r
2945 \r
2946 void AddHitTest(unsigned short ObjNum)\r
2947 {\r
2948     unsigned short i;\r
2949 \r
2950     for(i = 0; i < MAX_HITTESTS; i++)\r
2951     {\r
2952         if(HitTests[i] == 0xFFFF)\r
2953         {\r
2954             HitTests[i] = ObjNum;\r
2955             return;\r
2956         }\r
2957     }\r
2958 }\r
2959 \r
2960 void RemoveHitTest(unsigned short ObjNum)\r
2961 {\r
2962     unsigned short i;\r
2963 \r
2964     for(i = 0; i < MAX_HITTESTS; i++)\r
2965     {\r
2966         if(HitTests[i] == ObjNum)\r
2967         {\r
2968             for(i = i; i < MAX_HITTESTS; i++)\r
2969                 HitTests[i] = HitTests[i + 1];\r
2970             HitTests[MAX_HITTESTS - 1] = 0xFFFF;\r
2971             break;\r
2972         }\r
2973     }\r
2974 }\r
2975 \r
2976 void FontPrint(unsigned char *Buffer, signed short sx, signed short y, unsigned short bgc)\r
2977 {\r
2978     unsigned long Offset;\r
2979     unsigned char CurChar;\r
2980     unsigned short CharOffset;\r
2981     signed short x;\r
2982 \r
2983     Offset = 0;\r
2984     x = sx;\r
2985     while((CurChar = Buffer[Offset++]) != 0)\r
2986     {\r
2987         switch(CurChar)\r
2988         {\r
2989             case 10:\r
2990                 y += 6;\r
2991                 break;\r
2992             case 13:\r
2993                 x = sx;\r
2994                 break;\r
2995             default:\r
2996                 if(AsciiTable2[CurChar] != 255)\r
2997                 {\r
2998                     if(bgc != 0)\r
2999                         DBFRect(x, y, x + FontBuffer[(AsciiTable2[CurChar] << 1) + 1], y + 4, bgc);\r
3000                     DBCopyBufferClip(x, y, (unsigned char *)&FontBuffer[FontBuffer[AsciiTable2[CurChar] << 1] + 512], FontBuffer[(AsciiTable2[CurChar] << 1) + 1], 5, 0);\r
3001                 } else {\r
3002                     if(bgc != 0)\r
3003                         DBFRect(x, y, x + 2, y + 4, bgc);\r
3004                 }\r
3005                 x += FontBuffer[(AsciiTable2[CurChar] << 1) + 1] + 1;\r
3006                 break;\r
3007         }\r
3008     }\r
3009 }\r
3010 \r
3011 void DBPrint(unsigned char *Buffer, signed short sx, signed short y, unsigned char bgc)\r
3012 {\r
3013     unsigned long Offset;\r
3014     unsigned char CurChar;\r
3015     signed short x;\r
3016 \r
3017     Offset = 0;\r
3018     x = sx;\r
3019     while((CurChar = Buffer[Offset++]) != 0)\r
3020     {\r
3021         switch(CurChar)\r
3022         {\r
3023             case 10:\r
3024                 y += 5;\r
3025                 break;\r
3026             case 13:\r
3027                 x = sx;\r
3028                 break;\r
3029             default:\r
3030                 if(AsciiTable[CurChar] != 65535)\r
3031                 {\r
3032                     DBCopyBufferClip(x, y, Caches[FontSprite]->Frames[AsciiTable[CurChar]], Caches[FontSprite]->w, Caches[FontSprite]->h, bgc);\r
3033                 } else {\r
3034                     if(bgc != 0)\r
3035                         DBFRect(x, y, x + 2, y + 3, MakeColor(0, 0, 0));\r
3036                 }\r
3037                 x += Caches[FontSprite]->w + 1;\r
3038                 break;\r
3039         }\r
3040     }\r
3041 }\r
3042 \r
3043 unsigned short WallAngle(unsigned short x, unsigned short y)\r
3044 {\r
3045    return(0);\r
3046 }\r
3047 \r
3048 void SpawnPixel(unsigned short x, unsigned short y, float xv, float yv, unsigned char Owner, unsigned char SetColor, unsigned char Explode, signed short Damage, unsigned long c)\r
3049 {\r
3050     unsigned short i;\r
3051 \r
3052     for(i = 0; i < MAX_PIXELS; i++)\r
3053     {\r
3054         if(Pixels[i]->Used == 0)\r
3055         {\r
3056             Pixels[i]->x = x;\r
3057             Pixels[i]->y = y;\r
3058             Pixels[i]->xv = xv;\r
3059             Pixels[i]->yv = yv;\r
3060             Pixels[i]->c = c;\r
3061             Pixels[i]->SetColor = SetColor;\r
3062             Pixels[i]->Explode = Explode;\r
3063             Pixels[i]->Damage = Damage;\r
3064             Pixels[i]->Owner = Owner;\r
3065             Pixels[i]->Used = 1;\r
3066             return;\r
3067         }\r
3068     }\r
3069 }\r
3070 \r
3071 void DrawLightning(signed short x1, signed short y1, signed short x2, signed short y2, signed short NumPoints, unsigned char Template)\r
3072 {\r
3073     unsigned short i;\r
3074     signed short x, y, fx, fy, nx, ny;\r
3075     unsigned short Dist;\r
3076     unsigned char Rad;\r
3077 \r
3078     fx = x1;\r
3079     fy = y1;\r
3080     if(NumPoints <= 0)\r
3081     {\r
3082         while((Dist = (unsigned short)sqrt(((x2 - fx) * (x2 - fx)) + ((y2 - fy) * (y2 - fy)))) > 10)\r
3083         {\r
3084             nx = fx + (((x2 - fx) * 10) / Dist);\r
3085             ny = fy + (((y2 - fy) * 10) / Dist);\r
3086             Rad = -NumPoints;\r
3087             while((GetMapPixel((x = nx + (signed short)(rand() % ((Rad * 2) + 1)) - Rad), (y = ny + (signed short)(rand() % ((Rad * 2) + 1)) - Rad), 1) & MAP_SHOOTABLE) == 0)\r
3088                 Rad++;\r
3089             //DrawLine(fx, fy, x, y, 0, 0, 1, Template);\r
3090             DrawLine(fx, fy, x, y, 0, 0, 1, Template);\r
3091             fx = x;\r
3092             fy = y;\r
3093         }\r
3094         DrawLine(fx, fy, x2, y2, 0, 0, 1, Template);\r
3095     } else {\r
3096         for(i = 0; i < NumPoints; i++)\r
3097         {\r
3098             x = x1 + (signed short)(((signed long)(x2 - x1) * (signed long)i) / (signed long)NumPoints);\r
3099             y = y1 + (signed short)(((signed long)(y2 - y1) * (signed long)i) / (signed long)NumPoints);\r
3100             x += (signed short)(rand() % 7) - 3;\r
3101             y += (signed short)(rand() % 7) - 3;\r
3102             DrawLine(fx, fy, x, y, 0, 0, 1, Template);\r
3103             fx = x;\r
3104             fy = y;\r
3105         }\r
3106     }\r
3107 }\r
3108 \r
3109 void DrawLine(signed short x1, signed short y1, signed short x2, signed short y2, unsigned long c1, unsigned long c2, unsigned char Method, unsigned char UseSprite)\r
3110 {\r
3111     static unsigned short i = 0;\r
3112     unsigned short Start;\r
3113 \r
3114     for(Start = i; i < MAX_LINES; i++)\r
3115     {\r
3116         if(Lines[i]->Used == 0)\r
3117         {\r
3118             Lines[i]->x1 = x1;\r
3119             Lines[i]->y1 = y1;\r
3120             Lines[i]->x2 = x2;\r
3121             Lines[i]->y2 = y2;\r
3122             Lines[i]->c1 = c1;\r
3123             Lines[i]->c2 = c2;\r
3124             Lines[i]->Transparent = Method;\r
3125             Lines[i]->UseSprite = UseSprite;\r
3126             Lines[i]->AnimTimer = 0;\r
3127             Lines[i]->CurFrame = 0;\r
3128             if(UseSprite == 0xFF)\r
3129                 Lines[i]->Used = 1;\r
3130             else\r
3131                 Lines[i]->Used = Caches[UseSprite]->AnimDelay * Caches[UseSprite]->NumFrames;\r
3132             return;\r
3133         }\r
3134     }\r
3135     for(i = 0; i < Start; i++)\r
3136     {\r
3137         if(Lines[i]->Used == 0)\r
3138         {\r
3139             Lines[i]->x1 = x1;\r
3140             Lines[i]->y1 = y1;\r
3141             Lines[i]->x2 = x2;\r
3142             Lines[i]->y2 = y2;\r
3143             Lines[i]->c1 = c1;\r
3144             Lines[i]->c2 = c2;\r
3145             Lines[i]->Transparent = Method;\r
3146             Lines[i]->UseSprite = UseSprite;\r
3147             Lines[i]->AnimTimer = 0;\r
3148             Lines[i]->CurFrame = 0;\r
3149             if(UseSprite == 0xFF)\r
3150                 Lines[i]->Used = 1;\r
3151             else\r
3152                 Lines[i]->Used = Caches[UseSprite]->AnimDelay * Caches[UseSprite]->NumFrames;\r
3153             return;\r
3154         }\r
3155     }\r
3156 }\r
3157 \r
3158 void DrawCircle(signed short x, signed short y, unsigned short r, unsigned long Color, unsigned char Transparent)\r
3159 {\r
3160     unsigned short i;\r
3161 \r
3162     for(i = 0; i < MAX_RASTERS; i++)\r
3163     {\r
3164         if(Rasters[i]->Used == 0)\r
3165         {\r
3166             Rasters[i]->x1 = x;\r
3167             Rasters[i]->y1 = y;\r
3168             Rasters[i]->x2 = r;\r
3169             Rasters[i]->Color = Color;\r
3170             Rasters[i]->Transparent = Transparent;\r
3171             Rasters[i]->Type = 1;\r
3172             Rasters[i]->Used = 1;\r
3173             return;\r
3174         }\r
3175     }\r
3176 }\r
3177 \r
3178 void DrawPoly(signed short x1, signed short y1, signed short x2, signed short y2, signed short x3, signed short y3, unsigned long Color, unsigned char Transparent)\r
3179 {\r
3180     unsigned short i;\r
3181 \r
3182     for(i = 0; i < MAX_RASTERS; i++)\r
3183     {\r
3184         if(Rasters[i]->Used == 0)\r
3185         {\r
3186             Rasters[i]->x1 = x1;\r
3187             Rasters[i]->y1 = y1;\r
3188             Rasters[i]->x2 = x2;\r
3189             Rasters[i]->y2 = y2;\r
3190             Rasters[i]->x3 = x3;\r
3191             Rasters[i]->y3 = y3;\r
3192             Rasters[i]->Color = Color;\r
3193             Rasters[i]->Transparent = Transparent;\r
3194             Rasters[i]->Type = 0;\r
3195             Rasters[i]->Used = 1;\r
3196             return;\r
3197         }\r
3198     }\r
3199 }\r
3200 \r
3201 unsigned short SpawnObject(unsigned short Class, unsigned char Owner, unsigned short x, unsigned short y, float xv, float yv)\r
3202 {\r
3203     static unsigned short i = 0;\r
3204     unsigned short Start;\r
3205 \r
3206     for(Start = i; i < MAX_OBJECTS; i++)\r
3207     {\r
3208         if(Objects[i]->Used == 0)\r
3209         {\r
3210             Objects[i]->x = (float)x;\r
3211             Objects[i]->y = (float)y;\r
3212             Objects[i]->xv = xv;\r
3213             Objects[i]->yv = yv;\r
3214             Objects[i]->Class = Class;\r
3215             Objects[i]->Owner = Owner;\r
3216             Objects[i]->TickTimer = 0;\r
3217             Objects[i]->TouchTimer = Classes[Class]->TouchDelay;\r
3218             Objects[i]->SpriteLink = (Classes[Class]->Sprite != 0xFF)?(SpawnSprite(Classes[Class]->Sprite, (signed short)x, (signed short)y, 0, 0, 0, Classes[Class]->StartFrame, Classes[Class]->TransSprite)):0xFFFF;\r
3219             Objects[i]->Used = 1;\r
3220             Regs[16] = i;\r
3221             Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[2]);                        //Init\r
3222             return(i);\r
3223         }\r
3224     }\r
3225     for(i = 0; i < Start; i++)\r
3226     {\r
3227         if(Objects[i]->Used == 0)\r
3228         {\r
3229             Objects[i]->x = (float)x;\r
3230             Objects[i]->y = (float)y;\r
3231             Objects[i]->xv = xv;\r
3232             Objects[i]->yv = yv;\r
3233             Objects[i]->Class = Class;\r
3234             Objects[i]->Owner = Owner;\r
3235             Objects[i]->TickTimer = 0;\r
3236             Objects[i]->TouchTimer = Classes[Class]->TouchDelay;\r
3237             Objects[i]->SpriteLink = (Classes[Class]->Sprite != 0xFF)?(SpawnSprite(Classes[Class]->Sprite, (signed short)x, (signed short)y, 0, 0, 0, Classes[Class]->StartFrame, Classes[Class]->TransSprite)):0xFFFF;\r
3238             Objects[i]->Used = 1;\r
3239             Regs[16] = i;\r
3240             Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[2]);                        //Init\r
3241             return(i);\r
3242         }\r
3243     }\r
3244     return(0xFFFF);\r
3245 }\r
3246 \r
3247 unsigned short GetObjectList(void)\r
3248 {\r
3249     unsigned char i;\r
3250 \r
3251     for(i = 0; i < MAX_OBJLISTS; i++)\r
3252     {\r
3253         if(ObjectLists[i]->Used == 0)\r
3254         {\r
3255             ObjectLists[i]->Objects[0].Object = 0xFFFF;\r
3256             ObjectLists[i]->NumObjects = 0;\r
3257             ObjectLists[i]->Used = 1;\r
3258             return(i);\r
3259         }\r
3260     }\r
3261     return(0xFFFF);\r
3262 }\r
3263 \r
3264 void ControlObjects(void)\r
3265 {\r
3266     unsigned short i, o;\r
3267     unsigned short Class;\r
3268     signed short fx, fy, nx, ny, dx, dy, x, y;\r
3269     signed short x1, y1, x2, y2, tx1, ty1, tx2, ty2;\r
3270     unsigned char PixelInfo, Collided, Template;\r
3271     unsigned short ObjNum, SpriteLink, TestFrame;\r
3272     unsigned char *FrameBuffer;\r
3273 \r
3274     for(i = 0; i < MAX_OBJECTS; i++)\r
3275     {\r
3276         if(Objects[i]->Used == 2)\r
3277             Objects[i]->Used = 0;\r
3278     }\r
3279     for(i = 0; i < MAX_OBJECTS; i++)\r
3280     {\r
3281         if(Objects[i]->Used == 1)\r
3282         {\r
3283             Class = Objects[i]->Class;\r
3284             fx = (signed short)Objects[i]->x;\r
3285             fy = (signed short)Objects[i]->y;\r
3286             Objects[i]->yv += Gravity * ((float)Classes[Class]->GravityMod / 10000);\r
3287             Objects[i]->x += Objects[i]->xv;\r
3288             Objects[i]->y += Objects[i]->yv;\r
3289             if(Objects[i]->TouchTimer > 0)\r
3290                 Objects[i]->TouchTimer--;\r
3291             nx = (signed short)Objects[i]->x;\r
3292             ny = (signed short)Objects[i]->y;\r
3293             dx = nx - fx;\r
3294             dy = ny - fy;\r
3295             if(dx < 0)\r
3296                 dx = -dx;\r
3297             if(dy < 0)\r
3298                 dy = -dy;\r
3299             if((dx > 1) || (dy > 1))\r
3300             {\r
3301                 ObjNum = i;\r
3302                 SpriteLink = Objects[i]->SpriteLink;\r
3303                 if(SpriteLink != 0xFFFF)\r
3304                     Template = Sprites[SpriteLink]->Template;\r
3305                 else\r
3306                     Template = 0xFF;\r
3307                 Collided = CollisionTest((signed short *)&fx, (signed short *)&fy, (signed short *)&nx, (signed short *)&ny, MAP_SHOOTABLE, Classes[Class]->RunHitTests, (unsigned short *)&ObjNum, Template, (Template == 0xFF)?0:Sprites[SpriteLink]->CurFrame);\r
3308             } else {\r
3309                 Collided = (GetMapPixel((unsigned short)nx, (unsigned short)ny, 1) & MAP_SHOOTABLE) == 0;\r
3310                 if(Classes[Class]->RunHitTests == 1)\r
3311                 {\r
3312                     x = nx;\r
3313                     y = ny;\r
3314                     if((SpriteLink = Objects[i]->SpriteLink) == 0xFFFF)\r
3315                     {\r
3316                         Template = 0xFF;\r
3317                     } else {\r
3318                         Template = Sprites[SpriteLink]->Template;\r
3319                         TestFrame = Sprites[SpriteLink]->CurFrame;\r
3320                     }\r
3321                     if((ObjNum = HitTest(x, y, i, Template, TestFrame)) != 0xFFFF)\r
3322                         Collided = 2;\r
3323                     /*for(o = 0; o < MAX_HITTESTS; o++)\r
3324                     {\r
3325                         if(HitTests[o] == 0xFFFF)\r
3326                             break;\r
3327                         if(HitTests[o] == i)\r
3328                             continue;\r
3329                         SpriteLink = Objects[HitTests[o]]->SpriteLink;\r
3330                         if(SpriteLink != 0xFFFF)\r
3331                         {\r
3332                             if(SpriteLink != 0xFFFF)\r
3333                                 Template = Sprites[SpriteLink]->Template;\r
3334                             else\r
3335                                 Template = 0xFF;\r
3336                             if(Objects[i]->SpriteLink != 0xFFFF)\r
3337                             {\r
3338                                 SpriteLink2 = Objects[i]->SpriteLink;\r
3339                                 TestFrame = Sprites[SpriteLink2]->CurFrame;\r
3340                                 Template2 = Sprites[SpriteLink2]->Template;\r
3341                             } else {\r
3342                                 SpriteLink2 = 0xFFFF;\r
3343                                 TestFrame = 0;\r
3344                                 Template2 = 0xFF;\r
3345                             }\r
3346                             if(Template2 == 0xFF)\r
3347                             {\r
3348                                 tx1 = x;\r
3349                                 ty1 = y;\r
3350                                 tx2 = x;\r
3351                                 ty2 = y;\r
3352                             } else {\r
3353                                 tx1 = x - Caches[Template2]->cx[TestFrame];\r
3354                                 ty1 = y - Caches[Template2]->cy[TestFrame];\r
3355                                 tx2 = x - Caches[Template2]->cx[TestFrame] + Caches[Template2]->w;\r
3356                                 ty2 = y - Caches[Template2]->cy[TestFrame] + Caches[Template2]->h;\r
3357                             }\r
3358                             if((tx2 >= Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame]) && (ty2 >= Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) && (tx1 < Sprites[SpriteLink]->x - Caches[Template]->cx[Sprites[SpriteLink]->CurFrame] + Caches[Template]->w) && (ty1 < Sprites[SpriteLink]->y - Caches[Template]->cy[Sprites[SpriteLink]->CurFrame] + Caches[Template]->h))\r
3359                             {\r
3360                                 if(Objects[i]->SpriteLink == 0xFFFF)\r
3361                                 {\r
3362                                     Offset = x - Sprites[SpriteLink]->x + Caches[Template]->cx[Sprites[SpriteLink]->CurFrame];\r
3363                                     Offset += (y - Sprites[SpriteLink]->y + Caches[Template]->cy[Sprites[SpriteLink]->CurFrame]) * Caches[Template]->w;\r
3364                                     FrameBuffer = Caches[Template]->Frames[Sprites[SpriteLink]->CurFrame];\r
3365                                     if((Offset < Caches[Template]->w * Caches[Template]->h) && (*(unsigned long *)&FrameBuffer[Offset << 2] != 0))\r
3366                                     {\r
3367                                         ObjNum = HitTests[o];\r
3368                                         Collided = 2;\r
3369                                         break;\r
3370                                     }\r
3371                                 } else {\r
3372                                     if(SpritesOverlap(Template2, TestFrame, Template, Sprites[SpriteLink]->CurFrame, Sprites[SpriteLink]->x - x, Sprites[SpriteLink]->y - y))\r
3373                                     {\r
3374                                         ObjNum = HitTests[o];\r
3375                                         Collided = 2;\r
3376                                         break;\r
3377                                     }\r
3378                                 }\r
3379                             }\r
3380                         }\r
3381                     }*/\r
3382                 }\r
3383             }\r
3384             if(Collided != 0)\r
3385             {\r
3386                 if((Collided == 2)?((Objects[i]->Owner != 0xFF)?((ObjNum == Players[Objects[i]->Owner]->Object)?(Objects[i]->TouchTimer == 0):1):1):1)\r
3387                 {\r
3388                     PixelInfo = GetMapPixel((unsigned short)nx, (unsigned short)ny, 1);\r
3389                     Regs[16] = i;\r
3390                     Regs[17] = fx;\r
3391                     Regs[18] = fy;\r
3392                     Regs[19] = ((PixelInfo & MAP_SHOOTABLE) == 0)?0:1;\r
3393                     Regs[20] = ((PixelInfo & MAP_WALKABLE) == 0)?0:1;\r
3394                     Regs[21] = ((PixelInfo & MAP_DESTROYABLE) == 0)?0:1;\r
3395                     Regs[22] = nx;\r
3396                     Regs[23] = ny;\r
3397                     Regs[24] = Collided;\r
3398                     Regs[25] = ObjNum;\r
3399                     Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[1]);                    //Touch\r
3400                 }\r
3401             }\r
3402             if((Classes[Class]->TickDelay != 0) && (Objects[i]->Used == 1))\r
3403             {\r
3404                 if(++Objects[i]->TickTimer >= Classes[Class]->TickDelay)\r
3405                 {\r
3406                     PixelInfo = GetMapPixel((unsigned short)Objects[i]->x, (unsigned short)Objects[i]->y, 1);\r
3407                     Objects[i]->TickTimer = 0;\r
3408                     Regs[16] = i;\r
3409                     Regs[17] = (signed short)Objects[i]->x;\r
3410                     Regs[18] = (signed short)Objects[i]->y;\r
3411                     Regs[19] = ((PixelInfo & MAP_SHOOTABLE) == 0)?0:1;\r
3412                     Regs[20] = ((PixelInfo & MAP_WALKABLE) == 0)?0:1;\r
3413                     Regs[21] = ((PixelInfo & MAP_DESTROYABLE) == 0)?0:1;\r
3414                     Execute(Classes[Objects[i]->Class]->Code, (signed short *)&Objects[i]->Variables[0], Classes[Class]->Scripts[0]);                    //Tick\r
3415                 }\r
3416             }\r
3417             if(Objects[i]->SpriteLink != 0xFFFF)\r
3418             {\r
3419                 Sprites[Objects[i]->SpriteLink]->x = (signed short)Objects[i]->x;\r
3420                 Sprites[Objects[i]->SpriteLink]->y = (signed short)Objects[i]->y;\r
3421             }\r
3422         }\r
3423     }\r
3424 }\r
3425 \r
3426 void ControlSprites(void)\r
3427 {\r
3428     unsigned short i;\r
3429     unsigned char Template;\r
3430 \r
3431     for(i = 0; i < MAX_SPRITES; i++)\r
3432     {\r
3433         if(Sprites[i]->Used == 1)\r
3434         {\r
3435             Template = Sprites[i]->Template;\r
3436             Sprites[i]->x += Sprites[i]->xv;\r
3437             Sprites[i]->y += Sprites[i]->yv;\r
3438             if(Sprites[i]->AnimDelay != 0xFF)\r
3439             {\r
3440                 if(++Sprites[i]->AnimTimer >= Sprites[i]->AnimDelay)\r
3441                 {\r
3442                     Sprites[i]->AnimTimer = 0;\r
3443                     if(++Sprites[i]->CurFrame >= Caches[Template]->NumFrames)\r
3444                     {\r
3445                         Sprites[i]->CurFrame = 0;\r
3446                         if(Sprites[i]->AnimCount > 0)\r
3447                         {\r
3448                             if(--Sprites[i]->AnimCount == 0)\r
3449                             {\r
3450                                 Sprites[i]->Used = 0;\r
3451                             }\r
3452                         }\r
3453                     }\r
3454                 }\r
3455             }\r
3456         }\r
3457     }\r
3458     for(i = 0; i < MAX_LINES; i++)\r
3459     {\r
3460         if(Lines[i]->Used > 0)\r
3461         {\r
3462             Lines[i]->Used--;\r
3463             if((Lines[i]->UseSprite != 0xFF) && (Caches[Lines[i]->UseSprite]->AnimDelay != 0xFF))\r
3464             {\r
3465                 if(++Lines[i]->AnimTimer >= Caches[Lines[i]->UseSprite]->AnimDelay)\r
3466                 {\r
3467                     Lines[i]->AnimTimer = 0;\r
3468                     if(++Lines[i]->CurFrame >= Caches[Lines[i]->UseSprite]->NumFrames)\r
3469                         Lines[i]->CurFrame = 0;\r
3470                 }\r
3471             }\r
3472         }\r
3473     }\r
3474     for(i = 0; i < MAX_RASTERS; i++)\r
3475         Rasters[i]->Used = 0;\r
3476 }\r
3477 \r
3478 void ControlPixels(void)\r
3479 {\r
3480     unsigned short i, o;\r
3481     signed short fx, fy, nx, ny, dx, dy, x, y;\r
3482     unsigned char Collided;\r
3483     unsigned short ObjNum, SpriteLink, Template, Offset;\r
3484     unsigned char *FrameBuffer;\r
3485 \r
3486     for(i = 0; i < MAX_PIXELS; i++)\r
3487     {\r
3488         if(Pixels[i]->Used == 1)\r
3489         {\r
3490             fx = (signed short)Pixels[i]->x;\r
3491             fy = (signed short)Pixels[i]->y;\r
3492             Pixels[i]->x += Pixels[i]->xv;\r
3493             Pixels[i]->y += Pixels[i]->yv;\r
3494             nx = (signed short)Pixels[i]->x;\r
3495             ny = (signed short)Pixels[i]->y;\r
3496             dx = nx - fx;\r
3497             dy = ny - fy;\r
3498             if(dx < 0)\r
3499                 dx = -dx;\r
3500             if(dy < 0)\r
3501                 dy = -dy;\r
3502             if((dx > 1) || (dy > 1))\r
3503             {\r
3504                 ObjNum = 0xFFFF;\r
3505                 Collided = CollisionTest((signed short *)&fx, (signed short *)&fy, (signed short *)&nx, (signed short *)&ny, MAP_SHOOTABLE, Pixels[i]->Explode, (unsigned short *)&ObjNum, 0xFF, 0);\r
3506             } else {\r
3507                 Collided = (GetMapPixel((unsigned short)Pixels[i]->x, (unsigned short)Pixels[i]->y, 1) & MAP_SHOOTABLE) == 0;\r
3508                 if(Pixels[i]->Explode == 1)\r
3509                 {\r
3510                     x = (signed short)Pixels[i]->x;\r
3511                     y = (signed short)Pixels[i]->y;\r
3512                     if((ObjNum = HitTest(x, y, 0xFFFF, 0xFF, 0)) != 0xFFFF)\r
3513                     {\r
3514                         Collided = 2;\r
3515                     }\r
3516                 }\r
3517             }\r
3518             Pixels[i]->yv += Gravity;\r
3519             if(Collided != 0)\r
3520             {\r
3521                 if(Pixels[i]->SetColor == 1)\r
3522                 {\r
3523                     SetMapPixel((unsigned short)nx, (unsigned short)ny, Pixels[i]->c, 0);\r
3524                 }\r
3525                 if(Pixels[i]->SetColor == 2)\r
3526                 {\r
3527                     if((GetMapPixel((unsigned short)fx, (unsigned short)fy, 1) & MAP_SHOOTABLE) == MAP_SHOOTABLE)\r
3528                     {\r
3529                         SetMapPixel((unsigned short)fx, (unsigned short)fy, Pixels[i]->c, 0);\r
3530                         SetMapPixel((unsigned short)fx, (unsigned short)fy, MAP_DESTROYABLE, 1);\r
3531                     }\r
3532                 }\r
3533                 if(Pixels[i]->Explode == 1)\r
3534                 {\r
3535                     if(Collided == 1)\r
3536                         SpawnExplosion((signed short)nx, (signed short)ny, 7, 0, 1);\r
3537                     if(Collided == 2)\r
3538                     {\r
3539                         Objects[ObjNum]->xv += Pixels[i]->xv * (float)Pixels[i]->Damage * 0.013;\r
3540                         Objects[ObjNum]->yv += Pixels[i]->yv * (float)Pixels[i]->Damage * 0.013;\r
3541                         Regs[16] = (signed short)ObjNum;\r
3542                         Regs[17] = Pixels[i]->Damage;\r
3543                         Regs[18] = (signed short)Pixels[i]->Owner;\r
3544                         Regs[19] = (signed short)Objects[ObjNum]->x;\r
3545                         Regs[20] = (signed short)Objects[ObjNum]->y;\r
3546                         Execute(Classes[Objects[ObjNum]->Class]->Code, (signed short *)&Objects[ObjNum]->Variables[0], Classes[Objects[ObjNum]->Class]->Scripts[3]);                        //TakeDamage\r
3547                     }\r
3548                 }\r
3549                 Pixels[i]->Used = 0;\r
3550             }\r
3551         }\r
3552     }\r
3553 }\r
3554 \r
3555 void CollVel(signed short x, signed short y, float *xv, float *yv, unsigned char Attributes)\r
3556 {\r
3557     float Temp;\r
3558     signed char xa, ya;\r
3559     unsigned char a1, a2;\r
3560 \r
3561     if(*xv < 0)\r
3562         xa = -1;\r
3563     else\r
3564         xa = 1;\r
3565     if(*yv < 0)\r
3566         ya = -1;\r
3567     else\r
3568         ya = 1;\r
3569     a1 = GetMapPixel(x, y + ya, 1) & Attributes;\r
3570     a2 = GetMapPixel(x + xa, y, 1) & Attributes;\r
3571     if(((a1 == 0) && (a2 == 0)) || ((a1 != 0) && (a2 != 0)))\r
3572     {\r
3573         Temp = *yv;\r
3574         *yv = *xv * (float)(xa * -ya);\r
3575         *xv = Temp * (float)(ya * -xa);\r
3576     } else {\r
3577         if(a1 == 0)\r
3578             *yv = -*yv;\r
3579         if(a2 == 0)\r
3580             *xv = -*xv;\r
3581     }\r
3582 }\r
3583 \r
3584 void ControlPlayers(void)\r
3585 {\r
3586     unsigned short i, o;\r
3587     unsigned short ObjNum;\r
3588     signed short PlayerAngle, CurWeapon;\r
3589 \r
3590     for(i = 0; i < MAX_PLAYERS; i++)\r
3591     {\r
3592         if(Players[i]->Used == 1)\r
3593         {\r
3594             ObjNum = Players[i]->Object;\r
3595             PlayerAngle = Players[i]->Angle;\r
3596             if(PlayerAngle > 90)\r
3597                 PlayerAngle -= 360;\r
3598             if(Players[i]->Dir == 1)\r
3599                 PlayerAngle = 180 - PlayerAngle;\r
3600             if(PlayerAngle < 0)\r
3601                 PlayerAngle += 360;\r
3602             for(o = 0; o < NUM_WEAPONS; o++)\r
3603             {\r
3604                 if(PWeapons[i][o]->Used == 1)\r
3605                 {\r
3606                     if(PWeapons[i][o]->FireTimer > 0)\r
3607                     {\r
3608                         if(++PWeapons[i][o]->FireTimer > Weapons[PWeapons[i][o]->Weapon]->FireDelay)\r
3609                             PWeapons[i][o]->FireTimer = 0;\r
3610                     }\r
3611                     if((PWeapons[i][o]->ReloadTimer > 0) && (Players[i]->CurWeapon == o))\r
3612                     {\r
3613                         if((Weapons[PWeapons[i][o]->Weapon]->MaxClips > 0) && (PWeapons[i][o]->NumClips == 0))\r
3614                         {\r
3615                             PWeapons[i][o]->ReloadTimer = 0;\r
3616                         } else {\r
3617                             if(++PWeapons[i][o]->ReloadTimer > Weapons[PWeapons[i][o]->Weapon]->ReloadDelay)\r
3618                             {\r
3619                                 PWeapons[i][o]->ReloadTimer = 0;\r
3620                                 PWeapons[i][o]->AmmoLeft = Weapons[PWeapons[i][o]->Weapon]->Ammo;\r
3621                                 PlaySound(2, 0, 0, MAX_SOUNDS - 1, 22050, 1);\r
3622                             }\r
3623                         }\r
3624                     }\r
3625                     Regs[16] = (signed short)ObjNum;\r
3626                     if(Players[i]->Dir == 0)\r
3627                     {\r
3628                         Regs[17] = (signed short)Objects[ObjNum]->x + 3 + Cosine[PlayerAngle] * 7;\r
3629                     } else {\r
3630                         Regs[17] = (signed short)Objects[ObjNum]->x - 1 + Cosine[PlayerAngle] * 7;\r
3631                     }\r
3632                     Regs[18] = (signed short)Objects[ObjNum]->y - 2 - Sine[PlayerAngle] * 7;\r
3633                     Regs[19] = (signed short)PlayerAngle;\r
3634                     Regs[20] = (signed short)i;\r
3635                     Regs[21] = (signed short)o;\r
3636                     Execute(Classes[Weapons[PWeapons[i][o]->Weapon]->Class]->Code, (signed short *)&PWeapons[i][o]->Vars[0], Classes[Weapons[PWeapons[i][o]->Weapon]->Class]->Scripts[1]);                                                      //Tick\r
3637                 }\r
3638             }\r
3639             Players[i]->Angle += Players[i]->AngleVel;\r
3640             if((signed short)Players[i]->Angle >= 360)\r
3641                 Players[i]->Angle -= 360;\r
3642             if((signed short)Players[i]->Angle < 0)\r
3643                 Players[i]->Angle += 360;\r
3644             if((Players[i]->Angle < 300) && (Players[i]->Angle > 180))\r
3645             {\r
3646                 Players[i]->Angle = 300;\r
3647                 Players[i]->AngleVel = 0;\r
3648             }\r
3649             if((Players[i]->Angle > 90) && (Players[i]->Angle <= 180))\r
3650             {\r
3651                 Players[i]->Angle = 90;\r
3652                 Players[i]->AngleVel = 0;\r
3653             }\r
3654             if(((Players[i]->Left != 0) ^ (Players[i]->Right != 0)) & (Players[i]->Change == 0))\r
3655             {\r
3656                 if(Players[i]->Left != 0)\r
3657                 {\r
3658                     if(((GetMapPixel((unsigned short)(Objects[ObjNum]->x) - 1, (unsigned short)(Objects[ObjNum]->y) - 1, 1) & MAP_WALKABLE) == MAP_WALKABLE) && (Objects[ObjNum]->xv > -1))\r
3659                         Objects[ObjNum]->xv -= 0.1;\r
3660                     Players[i]->Dir = 1;\r
3661                 }\r
3662                 if(Players[i]->Right != 0)\r
3663                 {\r
3664                     if(((GetMapPixel((unsigned short)(Objects[ObjNum]->x) + 1, (unsigned short)(Objects[ObjNum]->y) - 1, 1) & MAP_WALKABLE) == MAP_WALKABLE) && (Objects[ObjNum]->xv < 1))\r
3665                         Objects[ObjNum]->xv += 0.1;\r
3666                     Players[i]->Dir = 0;\r
3667                 }\r
3668             } else {\r
3669                 if((GetMapPixel((unsigned short)Objects[ObjNum]->x, (unsigned short)Objects[ObjNum]->y, 1) & MAP_WALKABLE) == 0)\r
3670                     Objects[ObjNum]->xv *= 0.9;\r
3671             }\r
3672             if((Players[i]->Change != 0) && (Players[i]->Left == 1))\r
3673             {\r
3674                 Players[i]->CurWeapon -= 1;\r
3675                 if(Players[i]->CurWeapon < 0)\r
3676                     Players[i]->CurWeapon += NUM_WEAPONS;\r
3677                 while(PWeapons[i][Players[i]->CurWeapon]->Used == 0)\r
3678                 {\r
3679                     Players[i]->CurWeapon -= 1;\r
3680                     if(Players[i]->CurWeapon < 0)\r
3681                         Players[i]->CurWeapon += NUM_WEAPONS;\r
3682                 }\r
3683             }\r
3684             if((Players[i]->Change != 0) && (Players[i]->Right == 1))\r
3685             {\r
3686                 Players[i]->CurWeapon += 1;\r
3687                 if(Players[i]->CurWeapon >= NUM_WEAPONS)\r
3688                     Players[i]->CurWeapon -= NUM_WEAPONS;\r
3689                 while(PWeapons[i][Players[i]->CurWeapon]->Used == 0)\r
3690                 {\r
3691                     Players[i]->CurWeapon += 1;\r
3692                     if(Players[i]->CurWeapon >= NUM_WEAPONS)\r
3693                         Players[i]->CurWeapon -= NUM_WEAPONS;\r
3694                 }\r
3695             }\r
3696             if((Players[i]->Up != 0) ^ (Players[i]->Down != 0))\r
3697             {\r
3698                 if((Players[i]->Up != 0) && (Players[i]->AngleVel < 3))\r
3699                     Players[i]->AngleVel += .5;\r
3700                 if((Players[i]->Down != 0) && (Players[i]->AngleVel > -3))\r
3701                     Players[i]->AngleVel -= .5;\r
3702             } else {\r
3703                 Players[i]->AngleVel *= .75;\r
3704             }\r
3705             PlayerAngle = Players[i]->Angle;\r
3706             if(PlayerAngle > 90)\r
3707                 PlayerAngle -= 360;\r
3708             if(Players[i]->Dir == 1)\r
3709                 PlayerAngle = 180 - PlayerAngle;\r
3710             if(PlayerAngle < 0)\r
3711                 PlayerAngle += 360;\r
3712             CurWeapon = Players[i]->CurWeapon;\r
3713             Players[i]->JustShot = 0;\r
3714             if((Players[i]->Shoot != 0) && (PWeapons[i][CurWeapon]->FireTimer == 0) && (PWeapons[i][CurWeapon]->ReloadTimer == 0) && ((Weapons[PWeapons[i][CurWeapon]->Weapon]->MaxClips > 0)?(PWeapons[i][CurWeapon]->NumClips > 0):1))\r
3715             {\r
3716                 PWeapons[i][Players[i]->CurWeapon]->FireTimer = 1;\r
3717                 if(Players[i]->Dir == 0)\r
3718                 {\r
3719                     Regs[16] = (signed short)Objects[ObjNum]->x + 3 + Cosine[PlayerAngle] * 7;\r
3720                 } else {\r
3721                     Regs[16] = (signed short)Objects[ObjNum]->x - 1 + Cosine[PlayerAngle] * 7;\r
3722                 }\r
3723                 Regs[17] = (signed short)Objects[ObjNum]->y - 2 - Sine[PlayerAngle] * 7;\r
3724                 Regs[18] = (signed short)PlayerAngle;\r
3725                 Regs[19] = (signed short)(Objects[ObjNum]->xv * 100);\r
3726                 Regs[20] = (signed short)(Objects[ObjNum]->yv * 100);\r
3727                 Regs[21] = (signed short)i;\r
3728                 if(Weapons[PWeapons[i][CurWeapon]->Weapon]->MaxClips > 0)\r
3729                     PWeapons[i][CurWeapon]->NumClips--;\r
3730                 Execute(Classes[Weapons[PWeapons[i][CurWeapon]->Weapon]->Class]->Code, (signed short *)&PWeapons[i][CurWeapon]->Vars[0], Classes[Weapons[PWeapons[i][CurWeapon]->Weapon]->Class]->Scripts[0]);                                                  //Fire\r
3731                 if(--PWeapons[i][CurWeapon]->AmmoLeft <= 0)\r
3732                     PWeapons[i][CurWeapon]->ReloadTimer = 1;\r
3733                 Players[i]->JustShot = 1;\r
3734             }\r
3735         }\r
3736     }\r
3737 }\r
3738 \r
3739 void SaveBitmap(unsigned char *Buffer, unsigned short w, unsigned short h, unsigned char *FileName)\r
3740 {\r
3741     KvidFile BMPFile;\r
3742     unsigned long LongBuffer;\r
3743     unsigned short x, y;\r
3744 \r
3745     if((CreateFile(FileName, &BMPFile, NULL, 0) == 0) || (BMPFile.CanWrite == 0))\r
3746         return;\r
3747     FileWrite((void *)"BM", 2, &BMPFile);\r
3748     LongBuffer = 54 + (w * h * 3) + ((w % 4) * h);\r
3749     FileWrite((void *)&LongBuffer, 4, &BMPFile);\r
3750     FileWrite((void *)"\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00", 12, &BMPFile);\r
3751     LongBuffer = w;\r
3752     FileWrite((void *)&LongBuffer, 4, &BMPFile);\r
3753     LongBuffer = h;\r
3754     FileWrite((void *)&LongBuffer, 4, &BMPFile);\r
3755     FileWrite((void *)"\x01\x00\x18\x00\x00\x00\x00\x00", 8, &BMPFile);\r
3756     LongBuffer = (w * h * 3) + ((w % 4) * h);\r
3757     FileWrite((void *)&LongBuffer, 4, &BMPFile);\r
3758     FileWrite((void *)"\xC4\x0E\x00\x00\xC4\x0E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, &BMPFile);\r
3759     LongBuffer = 0;\r
3760     for(y = 0; y < h; y++)\r
3761     {\r
3762         for(x = 0; x < w; x++)\r
3763         {\r
3764             FileWrite((void *)(Buffer + (x << 2) + ((h - y - 1) * 1280)), 3, &BMPFile);\r
3765         }\r
3766         FileWrite((void *)&LongBuffer, w % 4, &BMPFile);\r
3767     }\r
3768     FileClose(&BMPFile);\r
3769 }\r
3770 \r
3771 void ControlMasks(void)\r
3772 {\r
3773     unsigned short i, o, u;\r
3774     unsigned short x, y, w, h;\r
3775     unsigned short R, G, B;\r
3776     unsigned char Colors;\r
3777     unsigned char *Buffer;\r
3778     Color c;\r
3779 \r
3780     for(i = 0; i < MAX_PLAYERS; i++)\r
3781     {\r
3782         if(Players[i]->Used == 1)\r
3783         {\r
3784             w = Players[i]->VPointX2 - Players[i]->VPointX1 + 1;\r
3785             h = Players[i]->VPointY2 - Players[i]->VPointY1 + 1;\r
3786             for(o = 0; o < NUM_MASKS; o++)\r
3787             {\r
3788                 Buffer = Players[i]->Masks[o].Buffer;\r
3789                 for(u = 0; u < 16; u++)\r
3790                 {\r
3791                     if(Players[i]->Masks[o].Effects[u] == 0)\r
3792                         break;\r
3793                     switch(Players[i]->Masks[o].Effects[u])\r
3794                     {\r
3795                         case 1:\r
3796                             for(y = 0; y < h; y++)\r
3797                             {\r
3798                                 for(x = 0; x < w; x++)\r
3799                                 {\r
3800                                     *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + x) << 2));\r
3801                                     R = c.R; G = c.G; B = c.B;\r
3802                                     Colors = 1;\r
3803                                     if(x > 0)\r
3804                                     {\r
3805                                         *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + (x - 1)) << 2));\r
3806                                         R += c.R; G += c.G; B += c.B;\r
3807                                         Colors++;\r
3808                                     }\r
3809                                     if(x < w - 1)\r
3810                                     {\r
3811                                         *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + (x + 1)) << 2));\r
3812                                         R += c.R; G += c.G; B += c.B;\r
3813                                         Colors++;\r
3814                                     }\r
3815                                     if(y > 0)\r
3816                                     {\r
3817                                         *(unsigned long *)&c = *(unsigned long *)(Buffer + (((y - 1) * w + x) << 2));\r
3818                                         R += c.R; G += c.G; B += c.B;\r
3819                                         Colors++;\r
3820                                     }\r
3821                                     if(y < h - 1)\r
3822                                     {\r
3823                                         *(unsigned long *)&c = *(unsigned long *)(Buffer + (((y + 1) * w + x) << 2));\r
3824                                         R += c.R; G += c.G; B += c.B;\r
3825                                         Colors++;\r
3826                                     }\r
3827                                     *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + x) << 2));\r
3828                                     R /= Colors;\r
3829                                     G /= Colors;\r
3830                                     B /= Colors;\r
3831                                     if(R > c.R || G > c.G || B > c.B)\r
3832                                     {\r
3833                                         c.R = R;\r
3834                                         c.G = G;\r
3835                                         c.B = B;\r
3836                                     }\r
3837                                     if(c.R > 0)\r
3838                                         c.R--;\r
3839                                     if(c.G > 0)\r
3840                                         c.G--;\r
3841                                     if(c.B > 0)\r
3842                                         c.B--;\r
3843                                     *(unsigned long *)(Buffer + ((y * w + x) << 2)) = *(unsigned long *)&c;\r
3844                                 }\r
3845                             }\r
3846                             break;\r
3847                         case 2:\r
3848                             for(y = 0; y < h; y++)\r
3849                             {\r
3850                                 for(x = 0; x < w; x++)\r
3851                                 {\r
3852                                     *(unsigned long *)&c = *(unsigned long *)(Buffer + ((y * w + x) << 2));\r
3853                                     c.R /= 2;\r
3854                                     c.G /= 2;\r
3855                                     c.B /= 2;\r
3856                                     *(unsigned long *)(Buffer + ((y * w + x) << 2)) = *(unsigned long *)&c;\r
3857                                 }\r
3858                             }\r
3859                             break;\r
3860                     }\r
3861                 }\r
3862             }\r
3863         }\r
3864     }\r
3865 }\r
3866 \r
3867 unsigned char ControlMenu(unsigned char Key)\r
3868 {\r
3869     unsigned short i, o, x, y, Signature, l;\r
3870     KvidFile ModFile;\r
3871     unsigned char ValidLevel;\r
3872     DIR *d;\r
3873     struct dirent *de;\r
3874 \r
3875     //DBFRectTrans(100, 30, 220, 150, MakeColor(0, 64, 0), 2);\r
3876     DBLine(100, 30, 100, 150, MakeColor(0, 150, 0), MakeColor(0, 150, 0));\r
3877     DBLine(100, 30, 220, 30, MakeColor(0, 150, 0), MakeColor(0, 150, 0));\r
3878     DBLine(220, 30, 220, 150, MakeColor(0, 150, 0), MakeColor(0, 150, 0));\r
3879     DBLine(100, 150, 220, 150, MakeColor(0, 150, 0), MakeColor(0, 150, 0));\r
3880     DBLineTrans(101, 31, 101, 149, MakeColor(0, 150, 0), MakeColor(0, 150, 0), 2);\r
3881     DBLineTrans(101, 31, 219, 31, MakeColor(0, 150, 0), MakeColor(0, 150, 0), 2);\r
3882     DBLineTrans(219, 31, 219, 149, MakeColor(0, 150, 0), MakeColor(0, 150, 0), 2);\r
3883     DBLineTrans(101, 149, 219, 149, MakeColor(0, 150, 0), MakeColor(0, 150, 0), 2);\r
3884     DBFRectTrans(102, 32, 218, 148, MakeColor(0, 64, 0), 2);\r
3885     if((Key == 200) && (CurMenuItem > 0))\r
3886         CurMenuItem--;\r
3887     if((Key == 208) && (CurMenuItem < NumMenuItems - 1))\r
3888         CurMenuItem++;\r
3889     if(CurMenuItem < StartMenuItem)\r
3890         StartMenuItem = CurMenuItem;\r
3891     if(CurMenuItem >= (StartMenuItem + 18))\r
3892         StartMenuItem = CurMenuItem - 17;\r
3893     if(Key == 1)\r
3894     {\r
3895         if(MenuStackPos == 0)\r
3896         {\r
3897             Paused = MenuActive = 0;\r
3898         } else {\r
3899             LoadMenu(MenuStack[--MenuStackPos][0]);\r
3900             CurMenuItem = MenuStack[MenuStackPos][1];\r
3901             StartMenuItem = MenuStack[MenuStackPos][2];\r
3902         }\r
3903     }\r
3904     if(Key == 28)\r
3905     {\r
3906         switch(*MenuItems[0][CurMenuItem])\r
3907         {\r
3908             case 0:\r
3909                 MenuStack[MenuStackPos][0] = MenuID;\r
3910                 MenuStack[MenuStackPos][1] = CurMenuItem;\r
3911                 MenuStack[MenuStackPos++][2] = StartMenuItem;\r
3912                 LoadMenu((unsigned short)MenuItems[0][CurMenuItem][1]);\r
3913                 CurMenuItem = StartMenuItem = 0;\r
3914                 break;\r
3915             case 1:\r
3916                 if(InitVar() == 1)\r
3917                 {\r
3918                     MessageBox("Couldn't find the control files PLAYER1.CTR and PLAYER2.CTR!");\r
3919                     return(1);\r
3920                 }\r
3921                 if(LevelType == 0)\r
3922                 {\r
3923                     if(LoadLevel(LevelFileName) != 0)\r
3924                         LevelType = 1;\r
3925                 }\r
3926                 if(LevelType == 1)\r
3927                 {\r
3928                     ReInit();\r
3929                     RandomLevel();\r
3930                 }\r
3931                 if(LevelType == 2)\r
3932                 {\r
3933                     ReInit();\r
3934                     for(i = 0; i < 2; i++)\r
3935                     {\r
3936                         for(y = 0; y < LevelHeight; y++)\r
3937                         {\r
3938                             for(x = 0; x < LevelWidth; x++)\r
3939                             {\r
3940                                 SetMapPixel((signed short)x, (signed short)y, (unsigned char)((i == 0)?0:7), i);\r
3941                             }\r
3942                         }\r
3943                     }\r
3944                     strcpy(LevelFileName, "Empty");\r
3945                     DispLevelWidth = LevelWidth;\r
3946                     DispLevelHeight = LevelHeight;\r
3947                     SpawnObject(0, -1, 0, 0, 0, 0);\r
3948                 }\r
3949                 Paused = 0;\r
3950                 MenuActive = 0;\r
3951                 if(ModFileName == NULL)\r
3952                 {\r
3953                     PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
3954                 } else {\r
3955                     if(OpenFile(ModFileName, &ModFile) == 0)\r
3956                     {\r
3957                         PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
3958                     } else {\r
3959                         if(LoadMod(&ModFile) != 0)\r
3960                             PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
3961                         else\r
3962                             ModPlaying = 1;\r
3963                         FileClose(&ModFile);\r
3964                     }\r
3965                 }\r
3966                 LevelFinished = 0;\r
3967                 return(0);\r
3968             case 2:\r
3969                 return(1);\r
3970             case 3:\r
3971                 if(UseSound == 1)\r
3972                 {\r
3973                     TerminatePlayBack();\r
3974                     if(SBReset() == 0)\r
3975                     {\r
3976                         ReadyBuffer = 0;\r
3977                         BufferReady = 0;\r
3978                         FillBuffer();\r
3979                         ReadyBuffer = 1;\r
3980                         StartPlayBack();\r
3981                     } else {\r
3982                         UseSound = 0;\r
3983                     }\r
3984                 }\r
3985                 break;\r
3986             case 4:\r
3987                 LoadMenu(MenuStack[--MenuStackPos][0]);\r
3988                 CurMenuItem = MenuStack[MenuStackPos][1];\r
3989                 StartMenuItem = MenuStack[MenuStackPos][2];\r
3990                 break;\r
3991             case 5:\r
3992                 MenuStack[MenuStackPos][0] = MenuID;\r
3993                 MenuStack[MenuStackPos][1] = CurMenuItem;\r
3994                 MenuStack[MenuStackPos++][2] = StartMenuItem;\r
3995                 CurMenuItem = StartMenuItem = 0;\r
3996                 MenuItems[0][0] = "\x06";\r
3997                 strcpy(MenuItems[1][0], "Random");\r
3998                 MenuItems[0][1] = "\x07";\r
3999                 strcpy(MenuItems[1][1], "Empty");\r
4000                 NumMenuItems = 2;\r
4001                 if((d = opendir(".")) != NULL)\r
4002                 {\r
4003                     while((de = readdir(d)) != NULL)\r
4004                     {\r
4005                         if((l = strlen(de->d_name)) < 4)\r
4006                             continue;\r
4007                         if(!strcmp(de->d_name + l - 4, ".lev") ||\r
4008                            !strcmp(de->d_name + l - 4, ".bmp"))\r
4009                         {\r
4010                             MenuItems[0][NumMenuItems] = "\x08";\r
4011                             strcpy(MenuItems[1][NumMenuItems++], de->d_name);\r
4012                         }\r
4013                     }\r
4014                     closedir(d);\r
4015                 }\r
4016                 MenuItems[0][NumMenuItems] = "\x04";\r
4017                 strcpy(MenuItems[1][NumMenuItems++], "Return");\r
4018                 break;\r
4019             case 6:\r
4020                 LevelType = 1;\r
4021                 LoadMenu(MenuStack[--MenuStackPos][0]);\r
4022                 CurMenuItem = MenuStack[MenuStackPos][1];\r
4023                 StartMenuItem = MenuStack[MenuStackPos][2];\r
4024                 strcpy(LevelFileName, "Random");\r
4025                 DispLevelWidth = LevelWidth;\r
4026                 DispLevelHeight = LevelHeight;\r
4027                 break;\r
4028             case 7:\r
4029                 LevelType = 2;\r
4030                 LoadMenu(MenuStack[--MenuStackPos][0]);\r
4031                 CurMenuItem = MenuStack[MenuStackPos][1];\r
4032                 StartMenuItem = MenuStack[MenuStackPos][2];\r
4033                 strcpy(LevelFileName, "Empty");\r
4034                 DispLevelWidth = LevelWidth;\r
4035                 DispLevelHeight = LevelHeight;\r
4036                 break;\r
4037             case 8:\r
4038                 if(OpenFile(MenuItems[1][CurMenuItem], &ModFile) == 0)\r
4039                 {\r
4040                     sprintf(TextBuffer, "Couldn't open %s!", MenuItems[1][CurMenuItem]);\r
4041                     MessageBox(TextBuffer);\r
4042                     break;\r
4043                 }\r
4044                 FileRead((void *)&Signature, 2, &ModFile);\r
4045                 ValidLevel = 0;\r
4046                 if(Signature == 0x464B)\r
4047                 {\r
4048                     ValidLevel = 1;\r
4049                     FileRead((void *)&DispLevelWidth, 2, &ModFile);\r
4050                     FileRead((void *)&DispLevelHeight, 2, &ModFile);\r
4051                 }\r
4052                 if(Signature == 0x4C4E)\r
4053                 {\r
4054                     ValidLevel = 1;\r
4055                     FileRead((void *)&DispLevelWidth, 2, &ModFile);\r
4056                     FileRead((void *)&DispLevelHeight, 2, &ModFile);\r
4057                 }\r
4058                 if(Signature == 0x4D42)\r
4059                 {\r
4060                     FileSkip(&ModFile, 16);\r
4061                     ValidLevel = 1;\r
4062                     FileRead((void *)&DispLevelWidth, 2, &ModFile);\r
4063                     FileSkip(&ModFile, 2);\r
4064                     FileRead((void *)&DispLevelHeight, 2, &ModFile);\r
4065                 }\r
4066                 if(ValidLevel == 0)\r
4067                 {\r
4068                     sprintf(TextBuffer, "%s is not a valid level file!", MenuItems[1][CurMenuItem]);\r
4069                     MessageBox(TextBuffer);\r
4070                     break;\r
4071                 }\r
4072                 FileClose(&ModFile);\r
4073                 LevelType = 0;\r
4074                 strcpy(LevelFileName, MenuItems[1][CurMenuItem]);\r
4075                 LoadMenu(MenuStack[--MenuStackPos][0]);\r
4076                 CurMenuItem = MenuStack[MenuStackPos][1];\r
4077                 StartMenuItem = MenuStack[MenuStackPos][2];\r
4078                 break;\r
4079         }\r
4080     }\r
4081     for(i = 0; ((i + StartMenuItem) < NumMenuItems) && (i < 18); i++)\r
4082     {\r
4083         FontPrint(MenuItems[1][i + StartMenuItem], 110, 40 + (i * 6), 0);\r
4084         if((i + StartMenuItem) == CurMenuItem)\r
4085         {\r
4086             DBCopyBufferClipTrans(109 - Caches[30]->w, 42 + (i * 6) - ((Caches[30]->h - 1) >> 1), Caches[30]->Frames[0], Caches[30]->w, Caches[30]->h, 0, 0);\r
4087             for(o = 109; o < 210; o += Caches[31]->w)\r
4088                 DBCopyBufferClipTrans(o, 42 + (i * 6) - ((Caches[31]->h - 1) >> 1), Caches[31]->Frames[0], Caches[31]->w, Caches[31]->h, 0, 0);\r
4089             DBCopyBufferClipTrans(o, 42 + (i * 6) - ((Caches[30]->h - 1) >> 1), Caches[30]->Frames[1], Caches[30]->w, Caches[30]->h, 0, 0);\r
4090         }\r
4091     }\r
4092     return(0);\r
4093 }\r
4094 \r
4095 unsigned char MonoColor(unsigned long c)\r
4096 {\r
4097     Color Col;\r
4098 \r
4099     Col = *(Color *)&c;\r
4100     return((unsigned char)((Col.R + ((Col.G * 31) / 63) + Col.B) / 3));\r
4101 }\r
4102 \r
4103 unsigned long SmoothColor(unsigned long c1, unsigned long c2, unsigned long c3, unsigned long c4)\r
4104 {\r
4105     Color Col0, Col1, Col2, Col3, Col4;\r
4106 \r
4107     Col1 = *(Color *)&c1;\r
4108     Col2 = *(Color *)&c2;\r
4109     Col3 = *(Color *)&c3;\r
4110     Col4 = *(Color *)&c4;\r
4111     Col0.R = (Col1.R + Col2.R + Col3.R + Col4.R) >> 2;\r
4112     Col0.G = (Col1.G + Col2.G + Col3.G + Col4.G) >> 2;\r
4113     Col0.B = (Col1.B + Col2.B + Col3.B + Col4.B) >> 2;\r
4114     return(*(unsigned long *)&Col0);\r
4115 }\r
4116 \r
4117 void SmoothArea(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2)\r
4118 {\r
4119     unsigned short x, y;\r
4120     unsigned long c0, a1, a2, a3, a4, s;\r
4121 \r
4122     for(y = y1; y <= y2; y++)\r
4123     {\r
4124         for(x = x1; x <= x2; x++)\r
4125         {\r
4126             if(((GetMapPixel(x, y, 1) & MAP_WALKABLE) == 0) && ((GetMapPixel(x, y, 1) & MAP_DESTROYABLE) == MAP_DESTROYABLE))\r
4127             {\r
4128                 a1 = GetMapPixel((signed short)x - 1, y, 1);\r
4129                 a2 = GetMapPixel(x + 1, y, 1);\r
4130                 a3 = GetMapPixel(x, (signed short)y - 1, 1);\r
4131                 a4 = GetMapPixel(x, y + 1, 1);\r
4132                 c0 = 0;\r
4133                 if((a1 & MAP_WALKABLE) == 0)\r
4134                     c0++;\r
4135                 if((a2 & MAP_WALKABLE) == 0)\r
4136                     c0++;\r
4137                 if((a3 & MAP_WALKABLE) == 0)\r
4138                     c0++;\r
4139                 if((a4 & MAP_WALKABLE) == 0)\r
4140                     c0++;\r
4141                 if(c0 == 0)\r
4142                 {\r
4143                     SetMapPixel(x, y, MAP_WALKABLE | MAP_SHOOTABLE, 1);\r
4144                     SpawnPixel(x, y, ((float)(rand() % 100) - 50) / 50, ((float)(rand() % 100) - 50) / 50, 255, 2, 0, 0, GetMapPixel(x, y, 0));\r
4145                     SetMapPixel(x, y, 0, 0);\r
4146                 }\r
4147                 if(c0 < 4)\r
4148                 {\r
4149                     s = SmoothColor(GetMapPixel(x + 1, y, 0), GetMapPixel(x - 1, y, 0), GetMapPixel(x, y + 1, 0), GetMapPixel(x, y - 1, 0));\r
4150                     if(MonoColor(s) > 20)\r
4151                         SetMapPixel(x, y, s, 0);\r
4152                 }\r
4153             }\r
4154         }\r
4155     }\r
4156 }\r
4157 \r
4158 void SpawnExplosion(signed short x, signed short y, unsigned char StartFrame, unsigned char Smokes, unsigned char Sound)\r
4159 {\r
4160     unsigned short i, Result;\r
4161 \r
4162     Result = SpawnSprite(0, x, y, 0, 0, 1, StartFrame++, 1);\r
4163     CopyToMap(x - Caches[0]->cx[StartFrame], y - Caches[0]->cy[StartFrame], Caches[0]->Frames[StartFrame], Caches[0]->w, Caches[0]->h, 0, 1, 0, MAP_WALKABLE | MAP_SHOOTABLE | MAP_DESTROYABLE);\r
4164     SmoothArea(x - Caches[0]->cx[StartFrame], y - Caches[0]->cy[StartFrame], x - Caches[0]->cx[StartFrame] + Caches[0]->w, y - Caches[0]->cy[StartFrame] + Caches[0]->h);\r
4165     StartFrame--;\r
4166     if(Smokes > 0)\r
4167     {\r
4168         for(i = 0; i < Smokes; i++)\r
4169         {\r
4170             SpawnSprite(1, x + ((signed short)(rand() % 10) - 5), y + ((signed short)(rand() % 10) - 5), 0, -1, 1, 0, 2);\r
4171         }\r
4172     }\r
4173     if(Sound == 1)\r
4174     {\r
4175         if(StartFrame > 5)\r
4176             PlaySound((rand() % 2) + 4, 0, 22, 42, 22050, 1);\r
4177         else\r
4178             PlaySound(3, 0, 43, 63, 22050, 1);\r
4179     }\r
4180 }\r
4181 \r
4182 unsigned char ArgExist(unsigned short argc, unsigned char **argv, char *Match)\r
4183 {\r
4184     unsigned short i;\r
4185 \r
4186     for(i = 1; i < argc; i++)\r
4187     {\r
4188         if(strcasecmp(argv[i], Match) == 0)\r
4189             return(i);\r
4190     }\r
4191     return(0);\r
4192 }\r
4193 \r
4194 int main(int argc, unsigned char **argv)\r
4195 {\r
4196     unsigned short Result, x, y, i, o;\r
4197     unsigned short Attributes;\r
4198     signed short Size;\r
4199     unsigned long Cycles;\r
4200     unsigned char Finished;\r
4201     unsigned char c0, c1, c2, c3, c4;\r
4202     unsigned short w, h;\r
4203     unsigned char MFR;\r
4204     unsigned char Key;\r
4205     unsigned long Start;\r
4206     double TickCounts[5];\r
4207     Color C0, C1, C2, C3, C4, FC;\r
4208     ModEvent *Buffer;\r
4209     KvidFile ModFile;\r
4210     double StartTime, CurTime;\r
4211     unsigned char NetFuncAddr[6];\r
4212     unsigned char *RetBuffer;\r
4213     float fcx[5], fcy[5];\r
4214     float fcxi[5], fcyi[5];\r
4215 \r
4216     //*(unsigned long *)&NetFuncAddr[0] = 0x0040102E;\r
4217     //*(unsigned short *)&NetFuncAddr[4] = 0x0177;\r
4218     //RetBuffer = (unsigned char *)MakeFarCall(0, NULL, NetFuncAddr);\r
4219     DebugMode = 0;\r
4220     MFR = 0;\r
4221     c0 = c3 = 0;\r
4222     w = h = 0;\r
4223     if(argc > 1)\r
4224     {\r
4225         if(ArgExist(argc, argv, "/Debug") != 0)\r
4226             DebugMode = 1;\r
4227         if(ArgExist(argc, argv, "/FR") != 0)\r
4228             MFR = 1;\r
4229         if(ArgExist(argc, argv, "/Randomatiserad") != 0)\r
4230             c0 = 1;\r
4231         if(ArgExist(argc, argv, "/Empty") != 0)\r
4232             c0 = 2;\r
4233         if((c1 = (unsigned char)ArgExist(argc, argv, "/Bana")) != 0)\r
4234             c0 = 3;\r
4235         w = (unsigned short)ArgExist(argc, argv, "/Banbredd");\r
4236         h = (unsigned short)ArgExist(argc, argv, "/Banaltitud");\r
4237         if((c2 = (unsigned char)ArgExist(argc, argv, "/Bg")) != 0)\r
4238             c3 = 1;\r
4239     }\r
4240     switch(Init(&Result))\r
4241     {\r
4242         case 0:\r
4243             printf("SDL Failure\nQuitting...\n");\r
4244             Terminate();\r
4245             return(1);\r
4246         case 1:\r
4247             printf("VESA Failure\nQuitting...\n");\r
4248             Terminate();\r
4249             return(1);\r
4250         case 2:\r
4251             printf("Not enough memory!\n");\r
4252             Terminate();\r
4253             return(1);\r
4254         case 3:\r
4255             printf("Couldn't find the file KVID.DAT!\n");\r
4256             Terminate();\r
4257             return(1);\r
4258         case 4:\r
4259             printf("Datafile corrupted!\n");\r
4260             Terminate();\r
4261             return(1);\r
4262     }\r
4263     Players[0]->Used = 1;\r
4264     Players[1]->Used = 1;\r
4265     if(w > 0)\r
4266         LevelWidth = (unsigned short)atoi(argv[w + 1]);\r
4267     if(h > 0)\r
4268         LevelHeight = (unsigned short)atoi(argv[h + 1]);\r
4269     switch(c0)\r
4270     {\r
4271         case 0:\r
4272             strcpy(LevelFileName, "dm.lev");\r
4273             LevelType = 0;\r
4274             if(LoadLevel("dm.lev") != 0)\r
4275             {\r
4276                 RandomLevel();\r
4277                 LevelType = 1;\r
4278             }\r
4279             break;\r
4280         case 1:\r
4281             RandomLevel();\r
4282             LevelType = 1;\r
4283             break;\r
4284         case 2:\r
4285             for(i = 0; i < 2; i++)\r
4286             {\r
4287                 for(y = 0; y < LevelHeight; y++)\r
4288                 {\r
4289                     for(x = 0; x < LevelWidth; x++)\r
4290                     {\r
4291                         SetMapPixel((signed short)x, (signed short)y, (unsigned char)((i == 0)?0:7), i);\r
4292                     }\r
4293                 }\r
4294             }\r
4295             strcpy(LevelFileName, "Empty");\r
4296             SpawnObject(0, -1, 0, 0, 0, 0);\r
4297             LevelType = 2;\r
4298             break;\r
4299         case 3:\r
4300             strcpy(LevelFileName, argv[c1 + 1]);\r
4301             LevelType = 0;\r
4302             if(LoadLevel(argv[c1 + 1]) != 0)\r
4303             {\r
4304                 RandomLevel();\r
4305                 LevelType = 1;\r
4306             }\r
4307             break;\r
4308     }\r
4309     if(InitVar() == 1)\r
4310     {\r
4311         Terminate();\r
4312         printf("Couldn't find control files!\nShould be named PLAYER1.CTR and PLAYER2.CTR\n");\r
4313         return(1);\r
4314     }\r
4315     ModFileName = NULL;\r
4316     if(c3 == 0)\r
4317     {\r
4318         if(OpenFile("DefaultMod", &ModFile) == 0)\r
4319         {\r
4320             PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
4321         } else {\r
4322             if(LoadMod(&ModFile) != 0)\r
4323             {\r
4324                 PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
4325             } else {\r
4326                 ModPlaying = 1;\r
4327                 ModFileName = "DefaultMod";\r
4328             }\r
4329             FileClose(&ModFile);\r
4330         }\r
4331     } else {\r
4332         if(OpenFile(argv[c2 + 1], &ModFile) == 0)\r
4333         {\r
4334             PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
4335         } else {\r
4336             if(LoadMod(&ModFile) != 0)\r
4337             {\r
4338                 PlaySound(0, 1, 0, MAX_SOUNDS - 1, 22050, 1);\r
4339             } else {\r
4340                 ModPlaying = 1;\r
4341                 ModFileName = argv[c2 + 1];\r
4342             }\r
4343             FileClose(&ModFile);\r
4344         }\r
4345     }\r
4346     if(MFR == 1)\r
4347     {\r
4348         Start = (unsigned long)time(NULL);\r
4349         while((unsigned long)time(NULL) == Start);\r
4350         Start = (unsigned long)time(NULL);\r
4351     }\r
4352     Paused = 0;\r
4353     MenuActive = 0;\r
4354     Cycles = 0;\r
4355     Finished = 0;\r
4356     LevelFinished = 0;\r
4357     Size = 0;\r
4358     StartTime = 0;\r
4359     while(Finished == 0)\r
4360     {\r
4361         if(!MFR && !KeyTable[29])\r
4362         {\r
4363             CurTime = ntime();\r
4364             while(CurTime - StartTime < 0.02)\r
4365             {\r
4366                 usleep((unsigned long)((0.02 - (CurTime - StartTime)) * 1000000));\r
4367                 CurTime = ntime();\r
4368             }\r
4369         }\r
4370         StartTime = ntime();\r
4371         /*if(KeyTable[67] == 1)\r
4372           DebugMode = 1;\r
4373           if(KeyTable[68] == 1)\r
4374           DebugMode = 0;*/\r
4375         if(GetEvents())\r
4376             Finished = 1;\r
4377         for(i = 0; i < MAX_PLAYERS; i++)\r
4378         {\r
4379             Players[i]->Left = 0;\r
4380             Players[i]->Right = 0;\r
4381             Players[i]->Up = 0;\r
4382             Players[i]->Down = 0;\r
4383             Players[i]->Shoot = 0;\r
4384             Players[i]->Change = 0;\r
4385         }\r
4386         GetInputs();\r
4387         Key = ReadKey();\r
4388         if(Paused == 0)\r
4389             ControlPixels();\r
4390         TickCounts[0] = ntime();\r
4391         if(Paused == 0)\r
4392             ControlSprites();\r
4393         TickCounts[1] = ntime();\r
4394         if(Paused == 0)\r
4395             ControlObjects();\r
4396         TickCounts[2] = ntime();\r
4397         if(Paused == 0)\r
4398             ControlPlayers();\r
4399         TickCounts[3] = ntime();\r
4400         Cycles++;\r
4401         if(MFR == 1)\r
4402             if((unsigned long)time(NULL) - Start > 10)\r
4403                 Finished = 1;\r
4404         c0 = KeyTable[63] * 4;\r
4405         if(KeyTable[64] == 1) c0 += 8;\r
4406         if(KeyTable[65] == 1) c0 += 16;\r
4407         if(KeyTable[59] == 1) BGFrame = c0;\r
4408         if(KeyTable[60] == 1) BGFrame = c0 + 1;\r
4409         if(KeyTable[61] == 1) BGFrame = c0 + 2;\r
4410         if(KeyTable[62] == 1) BGFrame = c0 + 3;\r
4411         if(KeyTable[66] == 1)\r
4412         {\r
4413             x = rand() % LevelWidth;\r
4414             y = rand() % LevelHeight;\r
4415             while((GetMapPixel(x, y, 1) & MAP_SHOOTABLE) == 0)\r
4416             {\r
4417                 x = rand() % LevelWidth;\r
4418                 y = rand() % LevelHeight;\r
4419             }\r
4420             SpawnObject(145, -1, x, y, 0, 0);\r
4421         }\r
4422         if((Key == 1) && (LevelFinished == 0) && (MenuActive == 0))\r
4423         {\r
4424             LoadMenu(0);\r
4425             MenuStackPos = 0;\r
4426             CurMenuItem = StartMenuItem = 0;\r
4427             Paused = MenuActive ^= 1;\r
4428             Key = 0;\r
4429         }\r
4430         if(KeyTable[87] == 1)\r
4431         {\r
4432             while(KeyTable[87] == 1)\r
4433                 GetEvents();\r
4434             Objects[Players[1]->Object]->xv = 100;\r
4435         }\r
4436         ControlMasks();\r
4437         DrawScreen();\r
4438         TickCounts[4] = ntime();\r
4439         if(Key == 68)\r
4440             SetMode(!FullScreen);\r
4441         if(Key == 88)\r
4442             SaveBitmap(DblBuffer, 320, 200, "ss.bmp");\r
4443         if(MenuActive == 1)\r
4444         {\r
4445             if(ControlMenu(Key) == 1)\r
4446                 Finished = 1;\r
4447         }\r
4448         if((LevelFinished == 1) && ((MenuActive == 0) || (Paused == 0)))\r
4449         {\r
4450             LoadMenu(0);\r
4451             CurMenuItem = StartMenuItem = 0;\r
4452             Paused = MenuActive = 1;\r
4453         }\r
4454 #if PLAY_TIME > 0\r
4455         sprintf(TextBuffer, "Play time left: %li", (signed long)(PLAY_TIME - Cycles));\r
4456         DBPrint(TextBuffer, 0, 196, 255);\r
4457         if(Cycles >= PLAY_TIME)\r
4458             Finished = 1;\r
4459 #endif\r
4460         x = 0;\r
4461         if(Cycles % 5 == 0)\r
4462         {\r
4463             if(--FogX < -Caches[FogSprite]->w)\r
4464                 FogX += Caches[FogSprite]->w;\r
4465         }\r
4466         if(Cycles % 10 == 0)\r
4467         {\r
4468             if(--FogY < -Caches[FogSprite]->h)\r
4469                 FogY += Caches[FogSprite]->h;\r
4470         }\r
4471         for(i = 0; i < 5; i++)\r
4472         {\r
4473             for(o = 0; o < (320 * ((TickCounts[i] - CurTime) / 0.02)); o++)\r
4474             {\r
4475                 DBPSetC(x++, 199, MakeColor((i * 255) / 4, 0, ((4 - i) * 255) / 4));\r
4476             }\r
4477             CurTime = TickCounts[i];\r
4478         }\r
4479         if(KeyTable[203] == 1)\r
4480             Size--;\r
4481         if(KeyTable[205] == 1)\r
4482             Size++;\r
4483         if(Size < 0)\r
4484             Size += 360;\r
4485         if(Size >= 360)\r
4486             Size -= 360;\r
4487         //DBCopyBufferRotated(160, 100, Caches[47]->Frames[0], Caches[47]->w, Caches[47]->h, 0, Caches[47]->w >> 1, Caches[47]->h >> 1, Size);\r
4488         DBPSetC(160, 100, MakeColor(255, 0, 0));\r
4489         DisplayDB();\r
4490     }\r
4491     while(KeyTable[1] == 1)\r
4492         GetEvents();\r
4493     for(i = 0; i < 5; i++)\r
4494     {\r
4495         fcx[i] = (rand() % 320) + 1;\r
4496         fcy[i] = (rand() % 200) + 1;\r
4497         fcxi[i] = ((float)(rand() % 200) / 100) - 1;\r
4498         fcyi[i] = ((float)(rand() % 200) / 100) - 1;\r
4499     }\r
4500     while(KeyTable[1] == 0)\r
4501     {\r
4502         GetEvents();\r
4503         for(Start = 0; Start < 256000; Start += 4)\r
4504         {\r
4505             C0 = *(Color *)&DblBuffer[Start];\r
4506             if(Start >= 4)\r
4507                 C1 = *(Color *)&DblBuffer[Start - 4];\r
4508             if(Start < 255996)\r
4509                 C2 = *(Color *)&DblBuffer[Start + 4];\r
4510             if(Start >= 1280)\r
4511                 C3 = *(Color *)&DblBuffer[Start - 1280];\r
4512             if(Start < 254720)\r
4513                 C4 = *(Color *)&DblBuffer[Start + 1280];\r
4514             FC.R = (C0.R + C1.R + C2.R + C3.R + C4.R) / 5;\r
4515             FC.G = (C0.G + C1.G + C2.G + C3.G + C4.G) / 5;\r
4516             FC.B = (C0.B + C1.B + C2.B + C3.B + C4.B) / 5;\r
4517             *(unsigned long *)&DblBuffer[Start] = *(unsigned long *)&FC;\r
4518         }\r
4519         /*asm("\r
4520         movl $0, %%eax\r
4521         movd %%eax, %%mm2\r
4522         movl $0, %%ecx\r
4523         movd (%%edi), %%mm0\r
4524         punpcklbw %%mm2, %%mm0\r
4525         movd -1280(%%edi), %%mm1\r
4526         emms\r
4527         "\r
4528         :\r
4529         : "D" (DblBuffer)\r
4530         : "%eax", "%ecx"\r
4531         );*/\r
4532         /*DBFCircleFadedTrans(fcx[0], fcy[0], 50, MakeColor(0, 100, 0), 1, 0);\r
4533         DBFCircleFadedTrans(fcx[1], fcy[1], 50, MakeColor(0, 0, 100), 1, 0);\r
4534         DBFCircleFadedTrans(fcx[2], fcy[2], 50, MakeColor(100, 100, 0), 1, 0);\r
4535         DBFCircleFadedTrans(fcx[3], fcy[3], 50, MakeColor(100, 0, 50), 1, 0);\r
4536         DBFCircleFadedTrans(fcx[4], fcy[4], 50, MakeColor(100, 0, 0), 1, 0);\r
4537         for(i = 0; i < 5; i++)\r
4538         {\r
4539             fcx[i] += fcxi[i];\r
4540             fcy[i] += fcyi[i];\r
4541             if(fcx[i] > 270)\r
4542                 fcxi[i] = -fabs(fcxi[i]);\r
4543             if(fcx[i] < 50)\r
4544                 fcxi[i] = fabs(fcxi[i]);\r
4545             if(fcy[i] > 150)\r
4546                 fcyi[i] = -fabs(fcyi[i]);\r
4547             if(fcy[i] < 50)\r
4548                 fcyi[i] = fabs(fcyi[i]);\r
4549         }*/\r
4550         DisplayDB();\r
4551     }\r
4552     Terminate();\r
4553     printf("%lu\n", Cycles);\r
4554     return(0);\r
4555 }\r