1 /*
2  *  Open Fodder
3  *  ---------------
4  *
5  *  Copyright (C) 2008-2018 Open Fodder
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License along
18  *  with this program; if not, write to the Free Software Foundation, Inc.,
19  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22 
23 #include "stdafx.hpp"
24 
25 #include <algorithm>
26 
27 const uint8 cResource_PC_CD::byte_29921[0x100] = {
28     3,   3,   3,   3,   3,   3,   3,   3,   3,   3,
29     3,   3,   3,   3,   3,   3,   3,   3,   3,   3,
30     3,   3,   3,   3,   3,   3,   3,   3,   3,   3,
31     3,   3,   4,   4,   4,   4,   4,   4,   4,   4,
32     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
33     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
34     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
35     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
36     5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
37     5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
38     5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
39     5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
40     5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
41     5,   5,   5,   5,   5,   5,   5,   5,   5,   5,
42     5,   5,   5,   5,   6,   6,   6,   6,   6,   6,
43     6,   6,   6,   6,   6,   6,   6,   6,   6,   6,
44     6,   6,   6,   6,   6,   6,   6,   6,   6,   6,
45     6,   6,   6,   6,   6,   6,   6,   6,   6,   6,
46     6,   6,   6,   6,   6,   6,   6,   6,   6,   6,
47     6,   6,   7,   7,   7,   7,   7,   7,   7,   7,
48     7,   7,   7,   7,   7,   7,   7,   7,   7,   7,
49     7,   7,   7,   7,   7,   7,   7,   7,   7,   7,
50     7,   7,   7,   7,   7,   7,   7,   7,   7,   7,
51     7,   7,   7,   7,   7,   7,   7,   7,   7,   7,
52     8,   8,   8,   8,   8,   8,   8,   8,   8,   8,
53     8,   8,   8,   8,   8,   8
54 };
55 
56 const uint8 cResource_PC_CD::byte_29A21[0x101] = {
57     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
58     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
59     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
60     0,   0,   1,   1,   1,   1,   1,   1,   1,   1,
61     1,   1,   1,   1,   1,   1,   1,   1,   2,   2,
62     2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
63     2,   2,   2,   2,   3,   3,   3,   3,   3,   3,
64     3,   3,   3,   3,   3,   3,   3,   3,   3,   3,
65     4,   4,   4,   4,   4,   4,   4,   4,   5,   5,
66     5,   5,   5,   5,   5,   5,   6,   6,   6,   6,
67     6,   6,   6,   6,   7,   7,   7,   7,   7,   7,
68     7,   7,   8,   8,   8,   8,   8,   8,   8,   8,
69     9,   9,   9,   9,   9,   9,   9,   9,  10,  10,
70    10,  10,  10,  10,  10,  10,  11,  11,  11,  11,
71    11,  11,  11,  11,  12,  12,  12,  12,  13,  13,
72    13,  13,  14,  14,  14,  14,  15,  15,  15,  15,
73    16,  16,  16,  16,  17,  17,  17,  17,  18,  18,
74    18,  18,  19,  19,  19,  19,  20,  20,  20,  20,
75    21,  21,  21,  21,  22,  22,  22,  22,  23,  23,
76    23,  23,  24,  24,  25,  25,  26,  26,  27,  27,
77    28,  28,  29,  29,  30,  30,  31,  31,  32,  32,
78    33,  33,  34,  34,  35,  35,  36,  36,  37,  37,
79    38,  38,  39,  39,  40,  40,  41,  41,  42,  42,
80    43,  43,  44,  44,  45,  45,  46,  46,  47,  47,
81    48,  49,  50,  51,  52,  53,  54,  55,  56,  57,
82    58,  59,  60,  61,  62,  63, 0
83 };
84 
cResource_PC_CD(const std::string & pDataFile)85 cResource_PC_CD::cResource_PC_CD( const std::string& pDataFile ) : cResources() {
86 
87 	memset( word_26DBE, 0, 0x273 * 2 );
88 	memset( word_272A4, 0, 0x13A * 2 );
89 	memset( word_27518, 0, 0x273 * 2 );
90 	memset( word_279FE, 0, 0x273 * 2 );
91 
92 	memset( byte_27EE6, 0, 0x1A3C );
93 	byte_26DB0 = 0;
94 
95 	mBytesRead = word_26DA8 = word_26DBA = 0;
96 	word_26DAA = word_26DB4 = saveSI = saveBP = 0;
97 
98 
99 	mData = g_ResourceMan->FileRead(g_Fodder->mVersionCurrent->getDataFilePath(pDataFile));
100 	if (!mData) {
101 		std::cout << pDataFile << " not found\n";
102 		exit( 1 );
103 	}
104 
105 	headerLoad();
106 }
107 
~cResource_PC_CD()108 cResource_PC_CD::~cResource_PC_CD() {
109 
110 }
111 
headerLoad()112 bool cResource_PC_CD::headerLoad() {
113 	const uint8* Data = mData->data();
114 
115 	if(!Data)
116 		return false;
117 
118 	uint16 ptrEnd = readLE<uint16>( Data );
119 
120 	mFiles.clear();
121 
122 	for( uint16 ptr = 4; ptr != ptrEnd; ) {
123 		std::string	filename = std::string( (char*) &Data[ptr+1], Data[ptr] );
124 		++ptr;
125 
126 		std::transform( filename.begin(), filename.end(), filename.begin(), ::tolower );
127 
128 		cResource_File	File( filename, 0, 0 );
129 
130 		ptr += (uint16) File.mName.size();
131 
132 		// Start address and size
133 		File.mAddressStart	= readLE<uint32>( &Data[ptr] );
134 
135 		File.mSize			= readLE<uint32>( &Data[ptr + 4] );
136 
137 		ptr += 8;
138 
139 		mFiles.push_back( File );
140 	}
141 
142 	return true;
143 }
144 
ExtractFiles()145 void cResource_PC_CD::ExtractFiles() {
146 
147 	for (auto File : mFiles) {
148 
149 		auto FileData = fileGet( File.mName );
150 		/*
151 		std::string Filename = local_PathGenerate( File.mName, "ExtractedData", eDataType::eData);
152 
153 		std::ofstream outfile( Filename, std::ofstream::binary );
154 		outfile.write( (const char*)FileData->data(), FileData->size() );
155 		outfile.close();*/
156 	}
157 }
158 
file_Get(cResource_File * pFile,bool pDecode)159 tSharedBuffer cResource_PC_CD::file_Get( cResource_File *pFile, bool pDecode ) {
160 	mDataCurrent = mData->data() + pFile->mAddressStart;
161 
162 	auto result = std::make_shared<std::vector<uint8>>();
163 
164 	for( uint32 i = 0; i < 0x1A3B; ++i )
165 		byte_27EE6[i] = 0x0;
166 
167 	if(!pDecode) {
168 
169 
170 	} else {
171 
172 		// seg006:0075
173 		mBytesRead = 0;
174 		byte_26DB0 = 0;
175 
176 		uint8 dl = data_Read( );
177 		uint8 dh = data_Read( );
178 
179 		uint16 dx = dl | (dh << 8);
180 		word_26DA8 = dx;
181 		word_26DBA = dx;
182 
183 		dl = data_Read( );
184 		dh = data_Read( );
185 		dx = dl | (dh << 8);
186 
187 		word_26DAA = dx;
188 		word_26DBA = (word_26DBA & 0xFFFF) | dx << 16;
189 
190 		if ((word_26DA8 | dx) == 0) {
191 			result->clear();
192 			return result;
193 		}
194 
195 		// seg006:00BA
196 		sub_26AA4();
197 
198 		for( uint32 i = 0; i < 0xFC4; ++i )
199 			byte_27EE6[i] = 0x20;
200 
201 		word_26DB4 = 0xFC4;
202 	}
203 
204 	for(;;) {
205 
206 		if( (word_26DBA >> 16) < 0 )
207 			break;
208 
209 		if( ! word_26DBA )
210 			break;
211 
212 		uint16 ax = sub_26C06();
213 
214 		if( (ax & 0xFF00) == 0 ) {
215 
216 			result->push_back(ax & 0xFF);
217 
218 			uint16 bx = word_26DB4;
219 			byte_27EE6[bx] = ax & 0xFF;
220 			++bx;
221 			bx &= 0xFFF;
222 
223 			word_26DB4 = bx;
224 			--word_26DBA;
225 			continue;
226 		}
227 
228 
229 		// seg006:012C
230 		uint16 saveAX = ax;
231 
232 		ax = sub_26CDF();
233 
234 		uint16 si = word_26DB4;
235 
236 		si -= ax;
237 		--si;
238 
239 		si &= 0x0FFF;
240 		ax = saveAX;
241 
242 		ax += 0xFF03;
243 		uint16 cx = ax;
244 
245 		word_26DBA -= cx;
246 		uint16 bx = word_26DB4;
247 
248 		for(;cx > 0; --cx) {
249 			uint8 al = byte_27EE6[si];
250 
251 			result->push_back( al );
252 			byte_27EE6[bx] = al;
253 			++bx;
254 
255 			bx &= 0xFFF;
256 			++si;
257 			si &= 0xFFF;
258 		}
259 
260 		word_26DB4 = bx;
261 
262 	}
263 
264 	return result;
265 }
266 
fileGet(std::string pFilename)267 tSharedBuffer cResource_PC_CD::fileGet( std::string pFilename ) {
268 	std::vector< cResource_File >::iterator		fileIT;
269 
270 	// Look for local overrides
271 	auto File = cResources::fileGet( pFilename );
272 	if (File->size())
273 		return File;
274 
275 	std::transform(pFilename.begin(), pFilename.end(), pFilename.begin(), ::tolower);
276 
277 	for (fileIT = mFiles.begin(); fileIT != mFiles.end(); ++fileIT) {
278 
279 		if (fileIT->mName == pFilename) {
280 
281 			return file_Get( &(*fileIT), true );
282 		}
283 	}
284 
285 	g_Debugger->Error("File " + pFilename + " Not Found in DAT");
286 	std::cout << "Total files inside DAT: " << mFiles.size() << "\n";
287 
288 	for (fileIT = mFiles.begin(); fileIT != mFiles.end(); ++fileIT)
289 		g_Debugger->Error(fileIT->mName + "\n");
290 
291 	exit( 1 );
292 	return File;
293 }
294 
sub_26CDF()295 uint16 cResource_PC_CD::sub_26CDF() {
296 
297 	uint8 dl = byte_26DB0;
298 	uint16 ax = 0;
299 	uint16 bp = saveBP;
300 
301 	for( uint16 cx = 8; cx > 0; --cx ) {
302 		if( dl == 0 ) {
303 			// seg006:3FC
304 			uint8 al, ah;
305 
306 			ah = data_Read();
307 			al = data_Read();
308 
309 			bp = (ah << 8) | al;
310 
311 			dl = 0x0F;
312 		} else
313 			--dl;
314 
315 		//seg006:3EF
316 		bool cf = false;
317 
318 		if(bp & 0x8000)
319 			cf = true;
320 
321 		bp <<= 1;
322 		ax <<= 1;
323 		if( cf )
324 			ax |= 0x01;
325 	}
326 
327 	byte_26DB0 = dl;
328 	uint16 bx = ax;
329 
330 	ax = 0;
331 	ax = byte_29A21[bx];
332 	bool cf = false;
333 
334 	if( ax & 1 )
335 		cf = true;
336 	ax >>= 1;
337 	if(cf)
338 		ax |= 0x8000;
339 
340 	cf = false;
341 	if( ax & 1 )
342 		cf = true;
343 	ax >>= 1;
344 	if(cf)
345 		ax |= 0x8000;
346 
347 	ax = ((ax & 0x00FF) << 8) | ((ax & 0xFF00) >> 8);
348 	uint16 saveAX = ax;
349 
350 	// seg006:41E
351 	uint16 cx = byte_29921[bx];
352 	cx &= 0xFF;
353 
354 	cx -= 2;
355 	dl = byte_26DB0;
356 
357 	for( ; cx > 0; --cx ) {
358 		if( dl == 0 ) {
359 			// seg006:0445
360 			uint8 al, ah;
361 
362 			ah = data_Read();
363 			al = data_Read();
364 
365 			bp = (ah << 8) | al;
366 
367 			dl = 0x10;
368 
369 		}
370 		//seg006:431
371 		bool cf = false;
372 
373 		if(bp & 0x8000)
374 			cf = true;
375 
376 		bp <<= 1;
377 		bx <<= 1;
378 		if( cf )
379 			bx |= 0x01;
380 
381 		--dl;
382 	}
383 
384 	byte_26DB0 = dl;
385 	bx &= 0x3F;
386 
387 	saveBP = bp;
388 	return saveAX | bx;
389 
390 }
391 
data_Read()392 uint8 cResource_PC_CD::data_Read() {
393 	if( !mBytesRead ) {
394 		mCurPtr = mDataCurrent;
395 		mDataCurrent += 0xA00;
396 		mBytesRead = 0xA00;
397 	}
398 
399 	uint8 al = mCurPtr[0];
400 	++mCurPtr;
401 	--mBytesRead;
402 
403 	return al;
404 }
405 
sub_26AA4()406 void cResource_PC_CD::sub_26AA4() {
407 	uint16 cx = 0;
408 
409 	while( cx < 0x13A ) {
410 		uint16 bx = cx;
411 
412 		word_279FE[bx] = 1;
413 
414 		uint16 ax = cx;
415 		ax += 0x273;
416 
417 		word_27518[bx] = ax;
418 		word_272A4[bx] = cx;
419 		++cx;
420 	}
421 
422 	// seg006:01CA
423 	cx = 0;
424 	uint16 dx = 0x13A;
425 
426 	while( dx <= 0x272 ) {
427 		uint16 bx = cx;
428 
429 		word_26DBE[bx + 1] = dx;
430 		word_26DBE[bx] = dx;
431 
432 		uint16 ax = word_279FE[bx];
433 		ax += word_279FE[bx+1];
434 
435 		bx = dx;
436 		//bx <<= 1;
437 		word_279FE[bx]=  ax;
438 		word_27518[bx] = cx;
439 		cx += 2;
440 		++dx;
441 	}
442 
443 	word_27EE4 = -1;
444 	word_26DBE[0x272] = 0;
445 }
446 
sub_26C06()447 uint16 cResource_PC_CD::sub_26C06() {
448 	uint8 dl = byte_26DB0;
449 
450 	uint16 si = word_27518[0x272];
451 
452 	uint16 bp = saveBP;
453 	uint16 cx = 0;
454 
455 	for(;;) {
456 
457 		if( si < 0x273 ) {
458 
459 			if( dl ) {
460 				--dl;
461 
462 			} else {
463 
464 				// seg006:03CE
465 				uint16 ax = data_Read( );
466 				ax <<= 8;
467 				ax |= data_Read( );
468 
469 				bp = ax;
470 				dl = 0x0F;
471 			}
472 			// loc_26C1F
473 			if( bp & 0x8000 )
474 				++si;
475 
476 			bp <<= 1;
477 			//si <<= 1;
478 
479 			si = word_27518[si];
480 			continue;
481 
482 		} else {
483 			// loc_26C2D
484 			byte_26DB0 = dl;
485 			si -= 0x273;
486 
487 			saveSI = si;
488 			saveBP = bp;
489 
490 			if( word_279FE[0x272] == -32768 )
491 				sub_26B11();
492 
493 			//si <<= 1;
494 			si = word_272A4[ si ];
495 			cx = si;
496 
497 			do {
498 
499 				++word_279FE[si];
500 				bp = word_279FE[si];
501 
502 				uint16 di = si;
503 				uint16 dx = cx;
504 
505 				++di;
506 				//++di;
507 				++dx;
508 
509 				if( bp > (uint16) word_279FE[di] ) {
510 
511 					do {
512 						++di;
513 					} while( bp > (uint16) word_279FE[di] );
514 
515 					--di;
516 					dx = di;
517 
518 					uint16 tmp = word_279FE[di];
519 					word_279FE[di] = bp;
520 					bp = tmp;
521 					word_279FE[si] = bp;
522 
523 					uint16 bx = word_27518[si];
524 					bp = bx;
525 
526 					word_26DBE[bx] = dx;
527 					if( bp < 0x273 )
528 						word_26DBE[bx+1] = dx;
529 
530 					// loc_26C9C
531 					tmp = word_27518[di];
532 					word_27518[di] = bp;
533 					bp = tmp;
534 
535 					bx = bp;
536 
537 					word_26DBE[bx] = cx;
538 					if( bp < 0x273 )
539 						word_26DBE[bx+1] = cx;
540 
541 					word_27518[si] = bp;
542 
543 					si = di;
544 					cx = dx;
545 				}
546 
547 			si = word_26DBE[si];
548 			cx = si;
549 
550 			} while( cx );
551 
552 			bp = saveBP;
553 			return saveSI;
554 		}
555 	}
556 }
557 
sub_26B11()558 void cResource_PC_CD::sub_26B11() {
559 	uint16 cx = 0;
560 	uint16 dx = 0;
561 
562 	while( dx < 0x273 ) {
563 
564 		uint16 bx = dx;
565 		if( word_27518[bx] >= 0x273 ) {
566 			uint16 ax = word_279FE[bx];
567 			++ax;
568 			ax >>= 1;
569 
570 			uint16 bx = cx;
571 			word_279FE[bx] = ax;
572 			bx = dx;
573 			ax = word_27518[bx];
574 			bx = cx;
575 
576 			word_27518[bx] = ax;
577 			++cx;
578 		}
579 		++dx;
580 	};
581 
582 	dx = 0;
583 	cx = 0x13A;
584 
585 	uint16 bp;
586 	uint16 si;
587 	uint16 di;
588 
589 	do {
590 		bp = dx;
591 		++bp;
592 		uint16 bx = dx;
593 
594 		si = word_279FE[bx];
595 		si += word_279FE[bx + 1];
596 
597 		bx = cx;
598 
599 		word_279FE[bx] = si;
600 		bp = cx;
601 		--bp;
602 
603 		for(;;--bp) {
604 
605 			bx = bp;
606 			uint16 ax = word_279FE[bx];
607 
608 			if( ax <= si )
609 				break;
610 		}
611 
612 		++bp;
613 		di = cx;
614 		di -= bp;
615 
616 		// seg006:28B
617 		uint16 savedSI = si;
618 		uint16 savedCX = cx;
619 
620 		si = bp;
621 		si += di;
622 		//si <<= 1;
623 
624 		bx = si;
625 		--bx;
626 		--bx;
627 
628 		cx = 0;
629 
630 		while( cx < di ) {
631 			uint16 ax = word_279FE[bx];
632 			word_279FE[si] = ax;
633 			ax = word_27518[bx];
634 			word_27518[si] = ax;
635 
636 			--si;
637 			--bx;
638 			++cx;
639 		};
640 
641 		cx = savedCX;
642 		si = savedSI;
643 
644 		bx = bp;
645 		word_279FE[si] = si;
646 		word_27518[bx] = dx;
647 		dx ++;
648 		++cx;
649 
650 	} while( cx < 0x273 );
651 	// seg006:02D2
652 
653 	dx = 0;
654 
655 	while( dx < 0x273 ) {
656 
657 		uint16 bx = dx;
658 		bp = word_27518[bx];
659 		if( bp >= 0x273 ) {
660 			bx = bp;
661 			word_26DBE[bx] = dx;
662 		} else {
663 			bx = bp;
664 			word_26DBE[bx+1] = dx;
665 			word_26DBE[bx] = dx;
666 		}
667 
668 		++dx;
669 	}
670 }
671