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