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