diff options
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/id_ca.c')
-rw-r--r-- | apps/plugins/sdl/progs/wolf3d/id_ca.c | 1113 |
1 files changed, 1113 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/id_ca.c b/apps/plugins/sdl/progs/wolf3d/id_ca.c new file mode 100644 index 0000000000..c6131a9882 --- /dev/null +++ b/apps/plugins/sdl/progs/wolf3d/id_ca.c | |||
@@ -0,0 +1,1113 @@ | |||
1 | // ID_CA.C | ||
2 | |||
3 | // this has been customized for WOLF | ||
4 | |||
5 | /* | ||
6 | ============================================================================= | ||
7 | |||
8 | Id Software Caching Manager | ||
9 | --------------------------- | ||
10 | |||
11 | Must be started BEFORE the memory manager, because it needs to get the headers | ||
12 | loaded into the data segment | ||
13 | |||
14 | ============================================================================= | ||
15 | */ | ||
16 | |||
17 | #include <SDL.h> | ||
18 | |||
19 | |||
20 | #include "wl_def.h" | ||
21 | #pragma hdrstop | ||
22 | |||
23 | #define THREEBYTEGRSTARTS | ||
24 | |||
25 | /* | ||
26 | ============================================================================= | ||
27 | |||
28 | LOCAL CONSTANTS | ||
29 | |||
30 | ============================================================================= | ||
31 | */ | ||
32 | |||
33 | typedef struct | ||
34 | { | ||
35 | word bit0,bit1; // 0-255 is a character, > is a pointer to a node | ||
36 | } huffnode; | ||
37 | |||
38 | |||
39 | typedef struct | ||
40 | { | ||
41 | word RLEWtag; | ||
42 | int32_t headeroffsets[100]; | ||
43 | } mapfiletype; | ||
44 | |||
45 | |||
46 | /* | ||
47 | ============================================================================= | ||
48 | |||
49 | GLOBAL VARIABLES | ||
50 | |||
51 | ============================================================================= | ||
52 | */ | ||
53 | |||
54 | #define BUFFERSIZE 0x1000 | ||
55 | static int32_t bufferseg[BUFFERSIZE/4]; | ||
56 | |||
57 | int mapon; | ||
58 | |||
59 | word *mapsegs[MAPPLANES]; | ||
60 | static maptype* mapheaderseg[NUMMAPS]; | ||
61 | byte *audiosegs[NUMSNDCHUNKS]; | ||
62 | byte *grsegs[NUMCHUNKS]; | ||
63 | |||
64 | word RLEWtag; | ||
65 | |||
66 | int numEpisodesMissing = 0; | ||
67 | |||
68 | /* | ||
69 | ============================================================================= | ||
70 | |||
71 | LOCAL VARIABLES | ||
72 | |||
73 | ============================================================================= | ||
74 | */ | ||
75 | |||
76 | char extension[5]; // Need a string, not constant to change cache files | ||
77 | char graphext[5]; | ||
78 | char audioext[5]; | ||
79 | static const char gheadname[] = DATADIR "vgahead."; | ||
80 | static const char gfilename[] = DATADIR "vgagraph."; | ||
81 | static const char gdictname[] = DATADIR "vgadict."; | ||
82 | static const char mheadname[] = DATADIR "maphead."; | ||
83 | static const char mfilename[] = DATADIR "maptemp."; | ||
84 | static const char mfilecama[] = DATADIR "gamemaps."; | ||
85 | static const char aheadname[] = DATADIR "audiohed."; | ||
86 | static const char afilename[] = DATADIR "audiot."; | ||
87 | |||
88 | void CA_CannotOpen(const char *string); | ||
89 | |||
90 | static int32_t grstarts[NUMCHUNKS + 1]; | ||
91 | static int32_t* audiostarts; // array of offsets in audio / audiot | ||
92 | |||
93 | #ifdef GRHEADERLINKED | ||
94 | huffnode *grhuffman; | ||
95 | #else | ||
96 | huffnode grhuffman[255]; | ||
97 | #endif | ||
98 | |||
99 | int grhandle = -1; // handle to EGAGRAPH | ||
100 | int maphandle = -1; // handle to MAPTEMP / GAMEMAPS | ||
101 | int audiohandle = -1; // handle to AUDIOT / AUDIO | ||
102 | |||
103 | int32_t chunkcomplen,chunkexplen; | ||
104 | |||
105 | SDMode oldsoundmode; | ||
106 | |||
107 | |||
108 | static int32_t GRFILEPOS(const size_t idx) | ||
109 | { | ||
110 | assert(idx < lengthof(grstarts)); | ||
111 | return grstarts[idx]; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | ============================================================================= | ||
116 | |||
117 | LOW LEVEL ROUTINES | ||
118 | |||
119 | ============================================================================= | ||
120 | */ | ||
121 | |||
122 | /* | ||
123 | ============================ | ||
124 | = | ||
125 | = CAL_GetGrChunkLength | ||
126 | = | ||
127 | = Gets the length of an explicit length chunk (not tiles) | ||
128 | = The file pointer is positioned so the compressed data can be read in next. | ||
129 | = | ||
130 | ============================ | ||
131 | */ | ||
132 | |||
133 | void CAL_GetGrChunkLength (int chunk) | ||
134 | { | ||
135 | lseek(grhandle,GRFILEPOS(chunk),SEEK_SET); | ||
136 | read(grhandle,&chunkexplen,sizeof(chunkexplen)); | ||
137 | chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4; | ||
138 | } | ||
139 | |||
140 | |||
141 | /* | ||
142 | ========================== | ||
143 | = | ||
144 | = CA_WriteFile | ||
145 | = | ||
146 | = Writes a file from a memory buffer | ||
147 | = | ||
148 | ========================== | ||
149 | */ | ||
150 | |||
151 | boolean CA_WriteFile (const char *filename, void *ptr, int32_t length) | ||
152 | { | ||
153 | const int handle = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644); | ||
154 | if (handle == -1) | ||
155 | return false; | ||
156 | |||
157 | if (!write (handle,ptr,length)) | ||
158 | { | ||
159 | close (handle); | ||
160 | return false; | ||
161 | } | ||
162 | close (handle); | ||
163 | return true; | ||
164 | } | ||
165 | |||
166 | |||
167 | |||
168 | /* | ||
169 | ========================== | ||
170 | = | ||
171 | = CA_LoadFile | ||
172 | = | ||
173 | = Allocate space for and load a file | ||
174 | = | ||
175 | ========================== | ||
176 | */ | ||
177 | |||
178 | boolean CA_LoadFile (const char *filename, memptr *ptr) | ||
179 | { | ||
180 | int32_t size; | ||
181 | |||
182 | const int handle = open(filename, O_RDONLY | O_BINARY); | ||
183 | if (handle == -1) | ||
184 | return false; | ||
185 | |||
186 | size = lseek(handle, 0, SEEK_END); | ||
187 | lseek(handle, 0, SEEK_SET); | ||
188 | *ptr=malloc(size); | ||
189 | CHECKMALLOCRESULT(*ptr); | ||
190 | if (!read (handle,*ptr,size)) | ||
191 | { | ||
192 | close (handle); | ||
193 | return false; | ||
194 | } | ||
195 | close (handle); | ||
196 | return true; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | ============================================================================ | ||
201 | |||
202 | COMPRESSION routines, see JHUFF.C for more | ||
203 | |||
204 | ============================================================================ | ||
205 | */ | ||
206 | |||
207 | static void CAL_HuffExpand(byte *source, byte *dest, int32_t length, huffnode *hufftable) | ||
208 | { | ||
209 | byte *end; | ||
210 | huffnode *headptr, *huffptr; | ||
211 | |||
212 | if(!length || !dest) | ||
213 | { | ||
214 | Quit("length or dest is null!"); | ||
215 | return; | ||
216 | } | ||
217 | |||
218 | headptr = hufftable+254; // head node is always node 254 | ||
219 | |||
220 | int written = 0; | ||
221 | |||
222 | end=dest+length; | ||
223 | |||
224 | byte val = *source++; | ||
225 | byte mask = 1; | ||
226 | word nodeval; | ||
227 | huffptr = headptr; | ||
228 | while(1) | ||
229 | { | ||
230 | if(!(val & mask)) | ||
231 | nodeval = huffptr->bit0; | ||
232 | else | ||
233 | nodeval = huffptr->bit1; | ||
234 | if(mask==0x80) | ||
235 | { | ||
236 | val = *source++; | ||
237 | mask = 1; | ||
238 | } | ||
239 | else mask <<= 1; | ||
240 | |||
241 | if(nodeval<256) | ||
242 | { | ||
243 | *dest++ = (byte) nodeval; | ||
244 | written++; | ||
245 | huffptr = headptr; | ||
246 | if(dest>=end) break; | ||
247 | } | ||
248 | else | ||
249 | { | ||
250 | huffptr = hufftable + (nodeval - 256); | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | ====================== | ||
257 | = | ||
258 | = CAL_CarmackExpand | ||
259 | = | ||
260 | = Length is the length of the EXPANDED data | ||
261 | = | ||
262 | ====================== | ||
263 | */ | ||
264 | |||
265 | #define NEARTAG 0xa7 | ||
266 | #define FARTAG 0xa8 | ||
267 | |||
268 | void CAL_CarmackExpand (byte *source, word *dest, int length) | ||
269 | { | ||
270 | word ch,chhigh,count,offset; | ||
271 | byte *inptr; | ||
272 | word *copyptr, *outptr; | ||
273 | |||
274 | length/=2; | ||
275 | |||
276 | inptr = (byte *) source; | ||
277 | outptr = dest; | ||
278 | |||
279 | while (length>0) | ||
280 | { | ||
281 | ch = READWORD(&inptr); | ||
282 | chhigh = ch>>8; | ||
283 | if (chhigh == NEARTAG) | ||
284 | { | ||
285 | count = ch&0xff; | ||
286 | if (!count) | ||
287 | { // have to insert a word containing the tag byte | ||
288 | ch |= *inptr++; | ||
289 | *outptr++ = ch; | ||
290 | length--; | ||
291 | } | ||
292 | else | ||
293 | { | ||
294 | offset = *inptr++; | ||
295 | copyptr = outptr - offset; | ||
296 | length -= count; | ||
297 | if(length<0) return; | ||
298 | while (count--) | ||
299 | *outptr++ = *copyptr++; | ||
300 | } | ||
301 | } | ||
302 | else if (chhigh == FARTAG) | ||
303 | { | ||
304 | count = ch&0xff; | ||
305 | if (!count) | ||
306 | { // have to insert a word containing the tag byte | ||
307 | ch |= *inptr++; | ||
308 | *outptr++ = ch; | ||
309 | length --; | ||
310 | } | ||
311 | else | ||
312 | { | ||
313 | offset = READWORD(&inptr); | ||
314 | copyptr = dest + offset; | ||
315 | length -= count; | ||
316 | if(length<0) return; | ||
317 | while (count--) | ||
318 | *outptr++ = *copyptr++; | ||
319 | } | ||
320 | } | ||
321 | else | ||
322 | { | ||
323 | *outptr++ = ch; | ||
324 | length --; | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | ====================== | ||
331 | = | ||
332 | = CA_RLEWcompress | ||
333 | = | ||
334 | ====================== | ||
335 | */ | ||
336 | |||
337 | int32_t CA_RLEWCompress (word *source, int32_t length, word *dest, word rlewtag) | ||
338 | { | ||
339 | word value,count; | ||
340 | unsigned i; | ||
341 | word *start,*end; | ||
342 | |||
343 | start = dest; | ||
344 | |||
345 | end = source + (length+1)/2; | ||
346 | |||
347 | // | ||
348 | // compress it | ||
349 | // | ||
350 | do | ||
351 | { | ||
352 | count = 1; | ||
353 | value = *source++; | ||
354 | while (*source == value && source<end) | ||
355 | { | ||
356 | count++; | ||
357 | source++; | ||
358 | } | ||
359 | if (count>3 || value == rlewtag) | ||
360 | { | ||
361 | // | ||
362 | // send a tag / count / value string | ||
363 | // | ||
364 | *dest++ = rlewtag; | ||
365 | *dest++ = count; | ||
366 | *dest++ = value; | ||
367 | } | ||
368 | else | ||
369 | { | ||
370 | // | ||
371 | // send word without compressing | ||
372 | // | ||
373 | for (i=1;i<=count;i++) | ||
374 | *dest++ = value; | ||
375 | } | ||
376 | |||
377 | } while (source<end); | ||
378 | |||
379 | return (int32_t)(2*(dest-start)); | ||
380 | } | ||
381 | |||
382 | |||
383 | /* | ||
384 | ====================== | ||
385 | = | ||
386 | = CA_RLEWexpand | ||
387 | = length is EXPANDED length | ||
388 | = | ||
389 | ====================== | ||
390 | */ | ||
391 | |||
392 | void CA_RLEWexpand (word *source, word *dest, int32_t length, word rlewtag) | ||
393 | { | ||
394 | word value,count,i; | ||
395 | word *end=dest+length/2; | ||
396 | |||
397 | // | ||
398 | // expand it | ||
399 | // | ||
400 | do | ||
401 | { | ||
402 | value = *source++; | ||
403 | if (value != rlewtag) | ||
404 | // | ||
405 | // uncompressed | ||
406 | // | ||
407 | *dest++=value; | ||
408 | else | ||
409 | { | ||
410 | // | ||
411 | // compressed string | ||
412 | // | ||
413 | count = *source++; | ||
414 | value = *source++; | ||
415 | for (i=1;i<=count;i++) | ||
416 | *dest++ = value; | ||
417 | } | ||
418 | } while (dest<end); | ||
419 | } | ||
420 | |||
421 | |||
422 | |||
423 | /* | ||
424 | ============================================================================= | ||
425 | |||
426 | CACHE MANAGER ROUTINES | ||
427 | |||
428 | ============================================================================= | ||
429 | */ | ||
430 | |||
431 | |||
432 | /* | ||
433 | ====================== | ||
434 | = | ||
435 | = CAL_SetupGrFile | ||
436 | = | ||
437 | ====================== | ||
438 | */ | ||
439 | |||
440 | void CAL_SetupGrFile (void) | ||
441 | { | ||
442 | char fname[13 + sizeof(DATADIR)]; | ||
443 | int handle; | ||
444 | byte *compseg; | ||
445 | |||
446 | #ifdef GRHEADERLINKED | ||
447 | |||
448 | grhuffman = (huffnode *)&EGAdict; | ||
449 | grstarts = (int32_t _seg *)FP_SEG(&EGAhead); | ||
450 | |||
451 | #else | ||
452 | |||
453 | // | ||
454 | // load ???dict.ext (huffman dictionary for graphics files) | ||
455 | // | ||
456 | |||
457 | strcpy(fname,gdictname); | ||
458 | strcat(fname,graphext); | ||
459 | |||
460 | handle = open(fname, O_RDONLY | O_BINARY); | ||
461 | if (handle == -1) | ||
462 | CA_CannotOpen(fname); | ||
463 | |||
464 | read(handle, grhuffman, sizeof(grhuffman)); | ||
465 | close(handle); | ||
466 | |||
467 | // load the data offsets from ???head.ext | ||
468 | strcpy(fname,gheadname); | ||
469 | strcat(fname,graphext); | ||
470 | |||
471 | handle = open(fname, O_RDONLY | O_BINARY); | ||
472 | if (handle == -1) | ||
473 | CA_CannotOpen(fname); | ||
474 | |||
475 | long headersize = lseek(handle, 0, SEEK_END); | ||
476 | lseek(handle, 0, SEEK_SET); | ||
477 | |||
478 | #ifndef APOGEE_1_0 | ||
479 | int expectedsize = lengthof(grstarts) - numEpisodesMissing; | ||
480 | #else | ||
481 | int expectedsize = lengthof(grstarts); | ||
482 | #endif | ||
483 | |||
484 | if(!param_ignorenumchunks && headersize / 3 != (long) expectedsize) | ||
485 | Quit("Wolf4SDL was not compiled for these data files:\n" | ||
486 | "%s contains a wrong number of offsets (%i instead of %i)!\n\n" | ||
487 | "Please check whether you are using the right executable!\n" | ||
488 | "(For mod developers: perhaps you forgot to update NUMCHUNKS?)", | ||
489 | fname, headersize / 3, expectedsize); | ||
490 | |||
491 | byte data[lengthof(grstarts) * 3]; | ||
492 | read(handle, data, sizeof(data)); | ||
493 | close(handle); | ||
494 | |||
495 | const byte* d = data; | ||
496 | for (int32_t* i = grstarts; i != endof(grstarts); ++i) | ||
497 | { | ||
498 | const int32_t val = d[0] | d[1] << 8 | d[2] << 16; | ||
499 | *i = (val == 0x00FFFFFF ? -1 : val); | ||
500 | d += 3; | ||
501 | } | ||
502 | #endif | ||
503 | |||
504 | // | ||
505 | // Open the graphics file, leaving it open until the game is finished | ||
506 | // | ||
507 | strcpy(fname,gfilename); | ||
508 | strcat(fname,graphext); | ||
509 | |||
510 | grhandle = open(fname, O_RDONLY | O_BINARY); | ||
511 | if (grhandle == -1) | ||
512 | CA_CannotOpen(fname); | ||
513 | |||
514 | |||
515 | // | ||
516 | // load the pic and sprite headers into the arrays in the data segment | ||
517 | // | ||
518 | pictable=(pictabletype *) malloc(NUMPICS*sizeof(pictabletype)); | ||
519 | CHECKMALLOCRESULT(pictable); | ||
520 | CAL_GetGrChunkLength(STRUCTPIC); // position file pointer | ||
521 | compseg=(byte *) malloc(chunkcomplen); | ||
522 | CHECKMALLOCRESULT(compseg); | ||
523 | read (grhandle,compseg,chunkcomplen); | ||
524 | CAL_HuffExpand(compseg, (byte*)pictable, NUMPICS * sizeof(pictabletype), grhuffman); | ||
525 | free(compseg); | ||
526 | } | ||
527 | |||
528 | //========================================================================== | ||
529 | |||
530 | |||
531 | /* | ||
532 | ====================== | ||
533 | = | ||
534 | = CAL_SetupMapFile | ||
535 | = | ||
536 | ====================== | ||
537 | */ | ||
538 | |||
539 | void CAL_SetupMapFile (void) | ||
540 | { | ||
541 | int i; | ||
542 | int handle; | ||
543 | int32_t length,pos; | ||
544 | char fname[13 + sizeof(DATADIR)]; | ||
545 | |||
546 | // | ||
547 | // load maphead.ext (offsets and tileinfo for map file) | ||
548 | // | ||
549 | strcpy(fname,mheadname); | ||
550 | strcat(fname,extension); | ||
551 | |||
552 | handle = open(fname, O_RDONLY | O_BINARY); | ||
553 | if (handle == -1) | ||
554 | CA_CannotOpen(fname); | ||
555 | |||
556 | length = NUMMAPS*4+2; // used to be "filelength(handle);" | ||
557 | mapfiletype *tinf=(mapfiletype *) malloc(sizeof(mapfiletype)); | ||
558 | CHECKMALLOCRESULT(tinf); | ||
559 | read(handle, tinf, length); | ||
560 | close(handle); | ||
561 | |||
562 | RLEWtag=tinf->RLEWtag; | ||
563 | |||
564 | // | ||
565 | // open the data file | ||
566 | // | ||
567 | #ifdef CARMACIZED | ||
568 | strcpy(fname, mfilecama); | ||
569 | strcat(fname, extension); | ||
570 | |||
571 | maphandle = open(fname, O_RDONLY | O_BINARY); | ||
572 | if (maphandle == -1) | ||
573 | CA_CannotOpen(fname); | ||
574 | #else | ||
575 | strcpy(fname,mfilename); | ||
576 | strcat(fname,extension); | ||
577 | |||
578 | maphandle = open(fname, O_RDONLY | O_BINARY); | ||
579 | if (maphandle == -1) | ||
580 | CA_CannotOpen(fname); | ||
581 | #endif | ||
582 | |||
583 | // | ||
584 | // load all map header | ||
585 | // | ||
586 | for (i=0;i<NUMMAPS;i++) | ||
587 | { | ||
588 | pos = tinf->headeroffsets[i]; | ||
589 | if (pos<0) // $FFFFFFFF start is a sparse map | ||
590 | continue; | ||
591 | |||
592 | mapheaderseg[i]=(maptype *) malloc(sizeof(maptype)); | ||
593 | CHECKMALLOCRESULT(mapheaderseg[i]); | ||
594 | lseek(maphandle,pos,SEEK_SET); | ||
595 | read (maphandle,(memptr)mapheaderseg[i],sizeof(maptype)); | ||
596 | } | ||
597 | |||
598 | free(tinf); | ||
599 | |||
600 | // | ||
601 | // allocate space for 3 64*64 planes | ||
602 | // | ||
603 | for (i=0;i<MAPPLANES;i++) | ||
604 | { | ||
605 | mapsegs[i]=(word *) malloc(maparea*2); | ||
606 | CHECKMALLOCRESULT(mapsegs[i]); | ||
607 | } | ||
608 | } | ||
609 | |||
610 | |||
611 | //========================================================================== | ||
612 | |||
613 | |||
614 | /* | ||
615 | ====================== | ||
616 | = | ||
617 | = CAL_SetupAudioFile | ||
618 | = | ||
619 | ====================== | ||
620 | */ | ||
621 | |||
622 | void CAL_SetupAudioFile (void) | ||
623 | { | ||
624 | char fname[13 + sizeof(DATADIR)]; | ||
625 | |||
626 | // | ||
627 | // load audiohed.ext (offsets for audio file) | ||
628 | // | ||
629 | strcpy(fname,aheadname); | ||
630 | strcat(fname,audioext); | ||
631 | |||
632 | void* ptr; | ||
633 | if (!CA_LoadFile(fname, &ptr)) | ||
634 | CA_CannotOpen(fname); | ||
635 | audiostarts = (int32_t*)ptr; | ||
636 | |||
637 | // | ||
638 | // open the data file | ||
639 | // | ||
640 | strcpy(fname,afilename); | ||
641 | strcat(fname,audioext); | ||
642 | |||
643 | audiohandle = open(fname, O_RDONLY | O_BINARY); | ||
644 | if (audiohandle == -1) | ||
645 | CA_CannotOpen(fname); | ||
646 | } | ||
647 | |||
648 | //========================================================================== | ||
649 | |||
650 | |||
651 | /* | ||
652 | ====================== | ||
653 | = | ||
654 | = CA_Startup | ||
655 | = | ||
656 | = Open all files and load in headers | ||
657 | = | ||
658 | ====================== | ||
659 | */ | ||
660 | |||
661 | void CA_Startup (void) | ||
662 | { | ||
663 | #ifdef PROFILE | ||
664 | unlink ("PROFILE.TXT"); | ||
665 | profilehandle = open("PROFILE.TXT", O_CREAT | O_WRONLY | O_TEXT); | ||
666 | #endif | ||
667 | |||
668 | CAL_SetupMapFile (); | ||
669 | CAL_SetupGrFile (); | ||
670 | CAL_SetupAudioFile (); | ||
671 | |||
672 | mapon = -1; | ||
673 | } | ||
674 | |||
675 | //========================================================================== | ||
676 | |||
677 | |||
678 | /* | ||
679 | ====================== | ||
680 | = | ||
681 | = CA_Shutdown | ||
682 | = | ||
683 | = Closes all files | ||
684 | = | ||
685 | ====================== | ||
686 | */ | ||
687 | |||
688 | void CA_Shutdown (void) | ||
689 | { | ||
690 | int i,start; | ||
691 | |||
692 | if(maphandle != -1) | ||
693 | close(maphandle); | ||
694 | if(grhandle != -1) | ||
695 | close(grhandle); | ||
696 | if(audiohandle != -1) | ||
697 | close(audiohandle); | ||
698 | |||
699 | for(i=0; i<NUMCHUNKS; i++) | ||
700 | UNCACHEGRCHUNK(i); | ||
701 | free(pictable); | ||
702 | |||
703 | switch(oldsoundmode) | ||
704 | { | ||
705 | case sdm_Off: | ||
706 | return; | ||
707 | case sdm_PC: | ||
708 | start = STARTPCSOUNDS; | ||
709 | break; | ||
710 | case sdm_AdLib: | ||
711 | start = STARTADLIBSOUNDS; | ||
712 | break; | ||
713 | } | ||
714 | |||
715 | for(i=0; i<NUMSOUNDS; i++,start++) | ||
716 | UNCACHEAUDIOCHUNK(start); | ||
717 | } | ||
718 | |||
719 | //=========================================================================== | ||
720 | |||
721 | /* | ||
722 | ====================== | ||
723 | = | ||
724 | = CA_CacheAudioChunk | ||
725 | = | ||
726 | ====================== | ||
727 | */ | ||
728 | |||
729 | int32_t CA_CacheAudioChunk (int chunk) | ||
730 | { | ||
731 | #ifdef SOUND_ENABLE | ||
732 | int32_t pos = audiostarts[chunk]; | ||
733 | int32_t size = audiostarts[chunk+1]-pos; | ||
734 | |||
735 | if (audiosegs[chunk]) | ||
736 | return size; // already in memory | ||
737 | |||
738 | audiosegs[chunk]=(byte *) malloc(size); | ||
739 | CHECKMALLOCRESULT(audiosegs[chunk]); | ||
740 | |||
741 | lseek(audiohandle,pos,SEEK_SET); | ||
742 | read(audiohandle,audiosegs[chunk],size); | ||
743 | |||
744 | return size; | ||
745 | #endif | ||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | void CA_CacheAdlibSoundChunk (int chunk) | ||
750 | { | ||
751 | #ifdef SOUND_ENABLE | ||
752 | int32_t pos = audiostarts[chunk]; | ||
753 | int32_t size = audiostarts[chunk+1]-pos; | ||
754 | |||
755 | if (audiosegs[chunk]) | ||
756 | return; // already in memory | ||
757 | |||
758 | lseek(audiohandle, pos, SEEK_SET); | ||
759 | read(audiohandle, bufferseg, ORIG_ADLIBSOUND_SIZE - 1); // without data[1] | ||
760 | |||
761 | AdLibSound *sound = (AdLibSound *) malloc(size + sizeof(AdLibSound) - ORIG_ADLIBSOUND_SIZE); | ||
762 | CHECKMALLOCRESULT(sound); | ||
763 | |||
764 | byte *ptr = (byte *) bufferseg; | ||
765 | sound->common.length = READLONGWORD(&ptr); | ||
766 | sound->common.priority = READWORD(&ptr); | ||
767 | sound->inst.mChar = *ptr++; | ||
768 | sound->inst.cChar = *ptr++; | ||
769 | sound->inst.mScale = *ptr++; | ||
770 | sound->inst.cScale = *ptr++; | ||
771 | sound->inst.mAttack = *ptr++; | ||
772 | sound->inst.cAttack = *ptr++; | ||
773 | sound->inst.mSus = *ptr++; | ||
774 | sound->inst.cSus = *ptr++; | ||
775 | sound->inst.mWave = *ptr++; | ||
776 | sound->inst.cWave = *ptr++; | ||
777 | sound->inst.nConn = *ptr++; | ||
778 | sound->inst.voice = *ptr++; | ||
779 | sound->inst.mode = *ptr++; | ||
780 | sound->inst.unused[0] = *ptr++; | ||
781 | sound->inst.unused[1] = *ptr++; | ||
782 | sound->inst.unused[2] = *ptr++; | ||
783 | sound->block = *ptr++; | ||
784 | |||
785 | read(audiohandle, sound->data, size - ORIG_ADLIBSOUND_SIZE + 1); // + 1 because of byte data[1] | ||
786 | |||
787 | audiosegs[chunk]=(byte *) sound; | ||
788 | #endif | ||
789 | } | ||
790 | |||
791 | //=========================================================================== | ||
792 | |||
793 | /* | ||
794 | ====================== | ||
795 | = | ||
796 | = CA_LoadAllSounds | ||
797 | = | ||
798 | = Purges all sounds, then loads all new ones (mode switch) | ||
799 | = | ||
800 | ====================== | ||
801 | */ | ||
802 | |||
803 | void CA_LoadAllSounds (void) | ||
804 | { | ||
805 | #ifdef SOUND_ENABLE | ||
806 | unsigned start,i; | ||
807 | |||
808 | switch (oldsoundmode) | ||
809 | { | ||
810 | case sdm_Off: | ||
811 | goto cachein; | ||
812 | case sdm_PC: | ||
813 | start = STARTPCSOUNDS; | ||
814 | break; | ||
815 | case sdm_AdLib: | ||
816 | start = STARTADLIBSOUNDS; | ||
817 | break; | ||
818 | } | ||
819 | |||
820 | for (i=0;i<NUMSOUNDS;i++,start++) | ||
821 | UNCACHEAUDIOCHUNK(start); | ||
822 | |||
823 | cachein: | ||
824 | |||
825 | oldsoundmode = SoundMode; | ||
826 | |||
827 | switch (SoundMode) | ||
828 | { | ||
829 | case sdm_Off: | ||
830 | start = STARTADLIBSOUNDS; // needed for priorities... | ||
831 | break; | ||
832 | case sdm_PC: | ||
833 | start = STARTPCSOUNDS; | ||
834 | break; | ||
835 | case sdm_AdLib: | ||
836 | start = STARTADLIBSOUNDS; | ||
837 | break; | ||
838 | } | ||
839 | |||
840 | if(start == STARTADLIBSOUNDS) | ||
841 | { | ||
842 | for (i=0;i<NUMSOUNDS;i++,start++) | ||
843 | CA_CacheAdlibSoundChunk(start); | ||
844 | } | ||
845 | else | ||
846 | { | ||
847 | for (i=0;i<NUMSOUNDS;i++,start++) | ||
848 | CA_CacheAudioChunk(start); | ||
849 | } | ||
850 | #endif | ||
851 | } | ||
852 | |||
853 | //=========================================================================== | ||
854 | |||
855 | |||
856 | /* | ||
857 | ====================== | ||
858 | = | ||
859 | = CAL_ExpandGrChunk | ||
860 | = | ||
861 | = Does whatever is needed with a pointer to a compressed chunk | ||
862 | = | ||
863 | ====================== | ||
864 | */ | ||
865 | |||
866 | void CAL_ExpandGrChunk (int chunk, int32_t *source) | ||
867 | { | ||
868 | int32_t expanded; | ||
869 | |||
870 | if (chunk >= STARTTILE8 && chunk < STARTEXTERNS) | ||
871 | { | ||
872 | // | ||
873 | // expanded sizes of tile8/16/32 are implicit | ||
874 | // | ||
875 | |||
876 | #define BLOCK 64 | ||
877 | #define MASKBLOCK 128 | ||
878 | |||
879 | if (chunk<STARTTILE8M) // tile 8s are all in one chunk! | ||
880 | expanded = BLOCK*NUMTILE8; | ||
881 | else if (chunk<STARTTILE16) | ||
882 | expanded = MASKBLOCK*NUMTILE8M; | ||
883 | else if (chunk<STARTTILE16M) // all other tiles are one/chunk | ||
884 | expanded = BLOCK*4; | ||
885 | else if (chunk<STARTTILE32) | ||
886 | expanded = MASKBLOCK*4; | ||
887 | else if (chunk<STARTTILE32M) | ||
888 | expanded = BLOCK*16; | ||
889 | else | ||
890 | expanded = MASKBLOCK*16; | ||
891 | } | ||
892 | else | ||
893 | { | ||
894 | // | ||
895 | // everything else has an explicit size longword | ||
896 | // | ||
897 | expanded = *source++; | ||
898 | } | ||
899 | |||
900 | // | ||
901 | // allocate final space, decompress it, and free bigbuffer | ||
902 | // Sprites need to have shifts made and various other junk | ||
903 | // | ||
904 | grsegs[chunk]=(byte *) malloc(expanded); | ||
905 | CHECKMALLOCRESULT(grsegs[chunk]); | ||
906 | CAL_HuffExpand((byte *) source, grsegs[chunk], expanded, grhuffman); | ||
907 | } | ||
908 | |||
909 | |||
910 | /* | ||
911 | ====================== | ||
912 | = | ||
913 | = CA_CacheGrChunk | ||
914 | = | ||
915 | = Makes sure a given chunk is in memory, loadiing it if needed | ||
916 | = | ||
917 | ====================== | ||
918 | */ | ||
919 | |||
920 | void CA_CacheGrChunk (int chunk) | ||
921 | { | ||
922 | int32_t pos,compressed; | ||
923 | int32_t *source; | ||
924 | int next; | ||
925 | |||
926 | if (grsegs[chunk]) | ||
927 | return; // already in memory | ||
928 | |||
929 | // | ||
930 | // load the chunk into a buffer, either the miscbuffer if it fits, or allocate | ||
931 | // a larger buffer | ||
932 | // | ||
933 | pos = GRFILEPOS(chunk); | ||
934 | if (pos<0) // $FFFFFFFF start is a sparse tile | ||
935 | return; | ||
936 | |||
937 | next = chunk +1; | ||
938 | while (GRFILEPOS(next) == -1) // skip past any sparse tiles | ||
939 | next++; | ||
940 | |||
941 | compressed = GRFILEPOS(next)-pos; | ||
942 | |||
943 | lseek(grhandle,pos,SEEK_SET); | ||
944 | |||
945 | if (compressed<=BUFFERSIZE) | ||
946 | { | ||
947 | read(grhandle,bufferseg,compressed); | ||
948 | source = bufferseg; | ||
949 | } | ||
950 | else | ||
951 | { | ||
952 | source = (int32_t *) malloc(compressed); | ||
953 | CHECKMALLOCRESULT(source); | ||
954 | read(grhandle,source,compressed); | ||
955 | } | ||
956 | |||
957 | CAL_ExpandGrChunk (chunk,source); | ||
958 | |||
959 | if (compressed>BUFFERSIZE) | ||
960 | free(source); | ||
961 | } | ||
962 | |||
963 | |||
964 | |||
965 | //========================================================================== | ||
966 | |||
967 | /* | ||
968 | ====================== | ||
969 | = | ||
970 | = CA_CacheScreen | ||
971 | = | ||
972 | = Decompresses a chunk from disk straight onto the screen | ||
973 | = | ||
974 | ====================== | ||
975 | */ | ||
976 | |||
977 | void CA_CacheScreen (int chunk) | ||
978 | { | ||
979 | int32_t pos,compressed,expanded; | ||
980 | memptr bigbufferseg; | ||
981 | int32_t *source; | ||
982 | int next; | ||
983 | |||
984 | // | ||
985 | // load the chunk into a buffer | ||
986 | // | ||
987 | pos = GRFILEPOS(chunk); | ||
988 | next = chunk +1; | ||
989 | while (GRFILEPOS(next) == -1) // skip past any sparse tiles | ||
990 | next++; | ||
991 | compressed = GRFILEPOS(next)-pos; | ||
992 | |||
993 | lseek(grhandle,pos,SEEK_SET); | ||
994 | |||
995 | bigbufferseg=malloc(compressed); | ||
996 | CHECKMALLOCRESULT(bigbufferseg); | ||
997 | read(grhandle,bigbufferseg,compressed); | ||
998 | source = (int32_t *) bigbufferseg; | ||
999 | |||
1000 | expanded = *source++; | ||
1001 | |||
1002 | // | ||
1003 | // allocate final space, decompress it, and free bigbuffer | ||
1004 | // Sprites need to have shifts made and various other junk | ||
1005 | // | ||
1006 | byte *pic = (byte *) malloc(64000); | ||
1007 | CHECKMALLOCRESULT(pic); | ||
1008 | CAL_HuffExpand((byte *) source, pic, expanded, grhuffman); | ||
1009 | |||
1010 | byte *vbuf = LOCK(); | ||
1011 | for(int y = 0, scy = 0; y < 200; y++, scy += scaleFactor) | ||
1012 | { | ||
1013 | for(int x = 0, scx = 0; x < 320; x++, scx += scaleFactor) | ||
1014 | { | ||
1015 | byte col = pic[(y * 80 + (x >> 2)) + (x & 3) * 80 * 200]; | ||
1016 | for(unsigned i = 0; i < scaleFactor; i++) | ||
1017 | for(unsigned j = 0; j < scaleFactor; j++) | ||
1018 | vbuf[(scy + i) * curPitch + scx + j] = col; | ||
1019 | } | ||
1020 | } | ||
1021 | UNLOCK(); | ||
1022 | free(pic); | ||
1023 | free(bigbufferseg); | ||
1024 | } | ||
1025 | |||
1026 | //========================================================================== | ||
1027 | |||
1028 | /* | ||
1029 | ====================== | ||
1030 | = | ||
1031 | = CA_CacheMap | ||
1032 | = | ||
1033 | = WOLF: This is specialized for a 64*64 map size | ||
1034 | = | ||
1035 | ====================== | ||
1036 | */ | ||
1037 | |||
1038 | void CA_CacheMap (int mapnum) | ||
1039 | { | ||
1040 | int32_t pos,compressed; | ||
1041 | int plane; | ||
1042 | word *dest; | ||
1043 | memptr bigbufferseg; | ||
1044 | unsigned size; | ||
1045 | word *source; | ||
1046 | #ifdef CARMACIZED | ||
1047 | word *buffer2seg; | ||
1048 | int32_t expanded; | ||
1049 | #endif | ||
1050 | |||
1051 | mapon = mapnum; | ||
1052 | |||
1053 | // | ||
1054 | // load the planes into the allready allocated buffers | ||
1055 | // | ||
1056 | size = maparea*2; | ||
1057 | |||
1058 | for (plane = 0; plane<MAPPLANES; plane++) | ||
1059 | { | ||
1060 | pos = mapheaderseg[mapnum]->planestart[plane]; | ||
1061 | compressed = mapheaderseg[mapnum]->planelength[plane]; | ||
1062 | |||
1063 | dest = mapsegs[plane]; | ||
1064 | |||
1065 | lseek(maphandle,pos,SEEK_SET); | ||
1066 | if (compressed<=BUFFERSIZE) | ||
1067 | source = (word *) bufferseg; | ||
1068 | else | ||
1069 | { | ||
1070 | bigbufferseg=malloc(compressed); | ||
1071 | CHECKMALLOCRESULT(bigbufferseg); | ||
1072 | source = (word *) bigbufferseg; | ||
1073 | } | ||
1074 | |||
1075 | read(maphandle,source,compressed); | ||
1076 | #ifdef CARMACIZED | ||
1077 | // | ||
1078 | // unhuffman, then unRLEW | ||
1079 | // The huffman'd chunk has a two byte expanded length first | ||
1080 | // The resulting RLEW chunk also does, even though it's not really | ||
1081 | // needed | ||
1082 | // | ||
1083 | expanded = *source; | ||
1084 | source++; | ||
1085 | buffer2seg = (word *) malloc(expanded); | ||
1086 | CHECKMALLOCRESULT(buffer2seg); | ||
1087 | CAL_CarmackExpand((byte *) source, buffer2seg,expanded); | ||
1088 | CA_RLEWexpand(buffer2seg+1,dest,size,RLEWtag); | ||
1089 | free(buffer2seg); | ||
1090 | |||
1091 | #else | ||
1092 | // | ||
1093 | // unRLEW, skipping expanded length | ||
1094 | // | ||
1095 | CA_RLEWexpand (source+1,dest,size,RLEWtag); | ||
1096 | #endif | ||
1097 | |||
1098 | if (compressed>BUFFERSIZE) | ||
1099 | free(bigbufferseg); | ||
1100 | } | ||
1101 | } | ||
1102 | |||
1103 | //=========================================================================== | ||
1104 | |||
1105 | void CA_CannotOpen(const char *string) | ||
1106 | { | ||
1107 | char str[30]; | ||
1108 | |||
1109 | strcpy(str,"Can't open "); | ||
1110 | strcat(str,string); | ||
1111 | strcat(str,"!\n"); | ||
1112 | Quit (str); | ||
1113 | } | ||