Initial commit
This commit is contained in:
553
engines/glk/scott/c64_checksums.cpp
Normal file
553
engines/glk/scott/c64_checksums.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on ScottFree interpreter version 1.14 developed by Swansea
|
||||
* University Computer Society without disassembly of any other game
|
||||
* drivers, only of game databases as permitted by EEC law (for purposes
|
||||
* of compatibility).
|
||||
*
|
||||
* Licensed under GPLv2
|
||||
*
|
||||
* https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
|
||||
*/
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "glk/scott/scott.h"
|
||||
#include "glk/scott/globals.h"
|
||||
#include "glk/scott/c64_checksums.h"
|
||||
#include "glk/scott/definitions.h"
|
||||
#include "glk/scott/disk_image.h"
|
||||
#include "glk/scott/game_info.h"
|
||||
#include "glk/scott/resource.h"
|
||||
#include "glk/scott/saga_draw.h"
|
||||
#include "glk/scott/unp64/unp64_interface.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Scott {
|
||||
|
||||
#define MAX_LENGTH 300000
|
||||
#define MIN_LENGTH 24
|
||||
|
||||
enum FileType {
|
||||
UNKNOWN_FILE_TYPE,
|
||||
TYPE_D64,
|
||||
TYPE_T64
|
||||
};
|
||||
|
||||
struct C64Rec {
|
||||
GameIDType _id;
|
||||
size_t _length;
|
||||
uint16_t _chk;
|
||||
FileType _type;
|
||||
int _decompressIterations;
|
||||
const char *_switches;
|
||||
const char *_appendFile;
|
||||
int _parameter;
|
||||
size_t _copySource;
|
||||
size_t _copyDest;
|
||||
size_t _copySize;
|
||||
int _imgOffset;
|
||||
};
|
||||
|
||||
static C64Rec g_C64Registry[] = {
|
||||
{ BATON_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Mysterious Adventures C64 dsk 1
|
||||
{ TIME_MACHINE_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
{ ARROW1_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
{ ARROW2_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
{ PULSAR7_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
{ CIRCUS_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
|
||||
{ FEASIBILITY_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Mysterious Adventures C64 dsk 2
|
||||
{ AKYRZ_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
{ PERSEUS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
{ INDIANS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
{ WAXWORKS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
{ BATON_C64, 0x2ab00, 0x9dca, TYPE_D64, 2, nullptr, nullptr, 0, 0, 0, 0, 0 },
|
||||
|
||||
{ ROBIN_OF_SHERWOOD_C64, 0x2ab00, 0xcf9e, TYPE_D64, 1, nullptr, nullptr, 0, 0x1802, 0xbd27, 0x2000, 0 }, // Robin Of Sherwood D64 * unknown packer
|
||||
{ ROBIN_OF_SHERWOOD_C64, 0xb2ef, 0x7c44, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000, 0 }, // Robin Of Sherwood C64 (T64) * TCS Cruncher v2.0
|
||||
{ ROBIN_OF_SHERWOOD_C64, 0xb690, 0x7b61, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000, 0 }, // Robin Of Sherwood C64 (T64) alt * TCS Cruncher v2.0
|
||||
{ ROBIN_OF_SHERWOOD_C64, 0x8db6, 0x7853, TYPE_T64, 1, nullptr, nullptr, 0, 0xd7fb, 0xbd20, 0x2000, 0 }, // Robin Of Sherwood T64 alt 2 * PUCrunch
|
||||
|
||||
{ GREMLINS_C64, 0xdd94, 0x25a8, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Gremlins C64 (T64) version * Action Replay v4.x
|
||||
{ GREMLINS_C64, 0x2ab00, 0xc402, TYPE_D64, 0, nullptr, "G1", -0x8D, 0, 0, 0, 0 }, // Gremlins C64 (D64) version
|
||||
{ GREMLINS_C64, 0x2ab00, 0x3ccf, TYPE_D64, 0, nullptr, "G1", -0x8D, 0, 0, 0, 0 }, // Gremlins C64 (D64) version 2
|
||||
{ GREMLINS_C64, 0x2ab00, 0xabf8, TYPE_D64, 2, "-e0x1255",nullptr, 2, 0, 0, 0, 0 }, // Gremlins C64 (D64) version alt * ByteBoiler, Exomizer
|
||||
{ GREMLINS_C64, 0x2ab00, 0xa265, TYPE_D64, 2, "-e0x1255",nullptr, 2, 0, 0, 0, 0 }, // Gremlins C64 (D64) version alt 2 * ByteBoiler, Exomizer
|
||||
{ GREMLINS_GERMAN_C64, 0xc003, 0x558c, TYPE_T64, 1, nullptr, nullptr, 0, 0xd801, 0xc6c0, 0x1f00, 0 }, // German Gremlins C64 (T64) version * TBC Multicompactor v2.x
|
||||
{ GREMLINS_GERMAN_C64, 0x2ab00, 0x6729, TYPE_D64, 2, nullptr, nullptr, 0, 0xdc02, 0xcac1, 0x1f00, 0 }, // German Gremlins C64 (D64) version * Exomizer
|
||||
|
||||
{ SEAS_OF_BLOOD_C64, 0xa209, 0xf115, TYPE_T64, 6, "-e0x1000", nullptr, 3, 0xd802, 0xb07c, 0x2000, 0 }, // Seas of Blood C64 (T64) MasterCompressor / Relax -> ECA
|
||||
// Compacker -> Unknown -> MasterCompressor / Relax -> ECA
|
||||
// Compacker -> CCS Packer
|
||||
{ SEAS_OF_BLOOD_C64, 0x2ab00, 0x5c1d, TYPE_D64, 1, nullptr, nullptr, 0, 0xd802, 0xb07c, 0x2000, 0 }, // Seas of Blood C64 (D64) CCS Packer
|
||||
{ SEAS_OF_BLOOD_C64, 0x2ab00, 0xe308, TYPE_D64, 1, nullptr, nullptr, 0, 0xd802, 0xb07c, 0x2000, 0 }, // Seas of Blood C64 (D64) alt CCS Packer
|
||||
|
||||
{ CLAYMORGUE_C64, 0x6ff7, 0xe4ed, TYPE_T64, 3, nullptr, nullptr, 0, 0x855, 0x7352, 0x20, 0 }, // Sorcerer Of Claymorgue Castle C64 (T64), MasterCompressor / Relax
|
||||
// -> ECA Compacker -> MegaByte Cruncher v1.x Missing 17 pictures
|
||||
{ CLAYMORGUE_C64, 0x912f, 0xa69f, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20, 0 }, // Sorcerer Of Claymorgue Castle C64 (T64) alt, MegaByte Cruncher
|
||||
// v1.x Missing 17 pictures
|
||||
{ CLAYMORGUE_C64, 0xc0dd, 0x3701, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, -0x7fe },// Sorcerer Of Claymorgue Castle C64 (T64) alt 2, Trilogic Expert
|
||||
// v2.7
|
||||
{ CLAYMORGUE_C64, 0xbc5f, 0x492c, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20, 0 }, // Sorcerer Of Claymorgue Castle C64 (T64) alt 3, , Section8 Packer
|
||||
{ CLAYMORGUE_C64, 0x2ab00, 0xfd67, TYPE_D64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20, 0 }, // Sorcerer Of Claymorgue Castle C64 (D64), Section8 Packer
|
||||
|
||||
{ ADVENTURELAND_C64, 0x6a10, 0x1910, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Adventureland C64 (T64) CruelCrunch v2.2
|
||||
{ ADVENTURELAND_C64, 0x6a10, 0x1b10, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Adventureland C64 (T64) alt CruelCrunch v2.2
|
||||
{ ADVENTURELAND_C64, 0x2ab00, 0x6638, TYPE_D64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Adventureland C64 (D64) CruelCrunch v2.2
|
||||
{ ADVENTURELAND_C64, 0x2adab, 0x751f, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Adventureland C64 (D64) alt
|
||||
{ ADVENTURELAND_C64, 0x2adab, 0x64a4, TYPE_D64, 0, nullptr, "SAG1PIC", -0xa53, 0, 0, 0, 0x65af }, // Adventureland C64 (D64) alt 2
|
||||
|
||||
{ SAVAGE_ISLAND_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGEISLAND1+", 1, 0, 0, 0, 0 }, // Savage Island part 1 C64 (D64)
|
||||
{ SAVAGE_ISLAND2_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x178b", "SAVAGEISLAND2+", 1, 0, 0, 0, 0 }, // Savage Island part 2 C64 (D64)
|
||||
{ SAVAGE_ISLAND_C64, 0x2ab00, 0xc361, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGE ISLAND P1", 1, 0, 0, 0, 0 }, // Savage Island part 1 C64 (D64) alt
|
||||
{ SAVAGE_ISLAND2_C64, 0x2ab00, 0xc361, TYPE_D64, 1, nullptr, "SAVAGE ISLAND P2", 0, 0, 0, 0, 0 }, // Savage Island part 2 C64 (D64) alt
|
||||
|
||||
{ HULK_C64, 0x2ab00, 0xcdd8, TYPE_D64, 0, nullptr, nullptr, 0, 0x1806, 0xb801, 0x307, 0 }, // Questprobe 1 - The Hulk C64 (D64)
|
||||
{ SPIDERMAN_C64, 0x2ab00, 0xde56, TYPE_D64, 0, nullptr, nullptr, 0, 0x1801, 0xa801, 0x2000, 0 }, // Spiderman C64 (D64)
|
||||
{ SPIDERMAN_C64, 0x08e72, 0xb2f4, TYPE_T64, 3, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Spiderman C64 (T64) MasterCompressor / Relax -> ECA Compacker -> Section8 Packer
|
||||
|
||||
{ BATON_C64, 0x5170, 0xb240, TYPE_T64, 2, nullptr, nullptr, 0, 0, 0, 0, 0 }, // The Golden Baton C64, T64
|
||||
{ BATON_C64, 0x2ab00, 0xbfbf, TYPE_D64, 2, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Mysterious Adventures C64 dsk 1 alt
|
||||
{ FEASIBILITY_C64, 0x2ab00, 0x9c18, TYPE_D64, 2, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Mysterious Adventures C64 dsk 2 alt
|
||||
{ TIME_MACHINE_C64, 0x5032, 0x5635, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // The Time Machine C64
|
||||
{ ARROW1_C64, 0x5b46, 0x92db, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Arrow of Death part 1 C64
|
||||
{ ARROW2_C64, 0x5fe2, 0xe14f, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Arrow of Death part 2 C64
|
||||
{ PULSAR7_C64, 0x46bf, 0x1679, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Escape from Pulsar 7 C64
|
||||
{ CIRCUS_C64, 0x4269, 0xa449, TYPE_T64, 2, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Circus C64
|
||||
{ FEASIBILITY_C64, 0x5a7b, 0x0f48, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Feasibility Experiment C64
|
||||
{ AKYRZ_C64, 0x2ab00, 0x6cca, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, 0 }, // The Wizard of Akyrz C64
|
||||
{ AKYRZ_C64, 0x4be1, 0x5a00, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // The Wizard of Akyrz C64, T64
|
||||
{ PERSEUS_C64, 0x502b, 0x913b, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Perseus and Andromeda C64
|
||||
{ INDIANS_C64, 0x4f9f, 0xe6c8, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Ten Little Indians C64
|
||||
{ WAXWORKS_C64, 0x4a11, 0xa37a, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0, 0 }, // Waxworks C64
|
||||
|
||||
{ SUPERGRAN_C64, 0x726f, 0x0901, TYPE_T64, 1, nullptr, nullptr, 0, 0xd802, 0xc623, 0x1f00, 0 }, // Super Gran C64 (T64) PUCrunch Generic Hack
|
||||
|
||||
{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry);
|
||||
|
||||
uint8_t *getLargestFile(uint8_t *data, int length, int *newlength) {
|
||||
uint8_t *file = nullptr;
|
||||
*newlength = 0;
|
||||
DiskImage *d64 = diCreateFromData(data, length);
|
||||
if (d64) {
|
||||
RawDirEntry *largest = findLargestFileEntry(d64);
|
||||
if (largest) {
|
||||
ImageFile *c64file = diOpen(d64, largest->_rawname, largest->_type, "rb");
|
||||
if (c64file) {
|
||||
uint8_t *largeFile = new uint8_t[0xffff];
|
||||
*newlength = diRead(c64file, largeFile, 0xffff);
|
||||
file = new uint8_t[*newlength];
|
||||
memcpy(file, largeFile, *newlength);
|
||||
}
|
||||
}
|
||||
//di_free_image(d64);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
uint8_t *getFileNamed(uint8_t* data, int length, int* newLength, const char* name) {
|
||||
uint8_t *file = nullptr;
|
||||
*newLength = 0;
|
||||
DiskImage *d64 = diCreateFromData(data, length);
|
||||
byte rawname[100];
|
||||
diRawnameFromName(rawname, name);
|
||||
if (d64) {
|
||||
ImageFile *c64file = diOpen(d64, rawname, 0xC2, "rb");
|
||||
if (c64file) {
|
||||
uint8_t *buf = new uint8_t[0xffff];
|
||||
*newLength = diRead(c64file, buf, 0xffff);
|
||||
file = new uint8_t[*newLength];
|
||||
memcpy(file, buf, *newLength);
|
||||
delete[] buf;
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
int savageIslandMenu(uint8_t **sf, size_t *extent, int recIndex) {
|
||||
g_scott->output("This disk image contains two games. Select one.\n\n"
|
||||
"1. Savage Island part I\n"
|
||||
"2. Savage Island part II");
|
||||
|
||||
g_scott->glk_request_char_event(_G(_bottomWindow));
|
||||
|
||||
event_t ev;
|
||||
int result = 0;
|
||||
do {
|
||||
g_scott->glk_select(&ev);
|
||||
if (ev.type == evtype_CharInput) {
|
||||
if (ev.val1 == '1' || ev.val1 == '2') {
|
||||
result = ev.val1 - '0';
|
||||
} else {
|
||||
g_scott->glk_request_char_event(_G(_bottomWindow));
|
||||
}
|
||||
}
|
||||
|
||||
if (g_vm->shouldQuit())
|
||||
return 0;
|
||||
} while (result == 0);
|
||||
|
||||
g_scott->glk_window_clear(_G(_bottomWindow));
|
||||
|
||||
recIndex += result - 1;
|
||||
|
||||
C64Rec rec = g_C64Registry[recIndex];
|
||||
int length;
|
||||
uint8_t *file = getFileNamed(*sf, *extent, &length, rec._appendFile);
|
||||
|
||||
if (file != nullptr) {
|
||||
if (rec._chk == 0xc361) {
|
||||
if (rec._switches != nullptr) {
|
||||
_G(_saveIslandAppendix1) = getFileNamed(*sf, *extent, &_G(_saveIslandAppendix1Length), "SI1PC1");
|
||||
_G(_saveIslandAppendix2) = getFileNamed(*sf, *extent, &_G(_saveIslandAppendix2Length), "SI1PC2");
|
||||
} else {
|
||||
_G(_saveIslandAppendix1) = getFileNamed(*sf, *extent, &_G(_saveIslandAppendix1Length), "SI2PIC");
|
||||
}
|
||||
}
|
||||
delete[] *sf;
|
||||
*sf = file;
|
||||
*extent = length;
|
||||
if (_G(_saveIslandAppendix1Length) > 2)
|
||||
_G(_saveIslandAppendix1Length) -= 2;
|
||||
if (_G(_saveIslandAppendix2Length) > 2)
|
||||
_G(_saveIslandAppendix2Length) -= 2;
|
||||
return decrunchC64(sf, extent, rec);
|
||||
} else {
|
||||
error("savageIslandMenu: Failed loading file %s\n", rec._appendFile);
|
||||
}
|
||||
}
|
||||
|
||||
void appendSIfiles(uint8_t **sf, size_t *extent) {
|
||||
//int totalLength = *extent + _G(_saveIslandAppendix1Length) + _G(_saveIslandAppendix2Length);
|
||||
|
||||
uint8_t *megabuf = new uint8_t[0xFFFF];
|
||||
memcpy(megabuf, *sf, *extent);
|
||||
delete[] *sf;
|
||||
int offset = 0x6202;
|
||||
|
||||
if (_G(_saveIslandAppendix1)) {
|
||||
memcpy(megabuf + offset, _G(_saveIslandAppendix1) + 2, _G(_saveIslandAppendix1Length));
|
||||
delete[] _G(_saveIslandAppendix1);
|
||||
}
|
||||
if (_G(_saveIslandAppendix2)) {
|
||||
memcpy(megabuf + offset + _G(_saveIslandAppendix1Length), _G(_saveIslandAppendix2) + 2, _G(_saveIslandAppendix2Length));
|
||||
delete[] _G(_saveIslandAppendix2);
|
||||
}
|
||||
*extent = offset + _G(_saveIslandAppendix1Length) + _G(_saveIslandAppendix2Length);
|
||||
*sf = new uint8_t[*extent];
|
||||
memcpy(*sf, megabuf, *extent);
|
||||
delete[] megabuf;
|
||||
}
|
||||
|
||||
int mysteriousMenu(uint8_t **sf, size_t *extent, int recindex) {
|
||||
recindex = 0;
|
||||
|
||||
g_scott->output("This disk image contains six games. Select one.\n\n"
|
||||
"1. The Golden Baton\n"
|
||||
"2. The Time Machine\n"
|
||||
"3. Arrow of Death part 1\n"
|
||||
"4. Arrow of Death part 2\n"
|
||||
"5. Escape from Pulsar 7\n"
|
||||
"6. Circus");
|
||||
|
||||
g_scott->glk_request_char_event(_G(_bottomWindow));
|
||||
|
||||
event_t ev;
|
||||
int result = 0;
|
||||
do {
|
||||
g_scott->glk_select(&ev);
|
||||
if (ev.type == evtype_CharInput) {
|
||||
if (ev.val1 >= '1' && ev.val1 <= '6') {
|
||||
result = ev.val1 - '0';
|
||||
} else {
|
||||
g_scott->glk_request_char_event(_G(_bottomWindow));
|
||||
}
|
||||
}
|
||||
|
||||
if (g_vm->shouldQuit())
|
||||
return 0;
|
||||
} while (result == 0);
|
||||
|
||||
g_scott->glk_window_clear(_G(_bottomWindow));
|
||||
|
||||
const char *filename = nullptr;
|
||||
switch (result) {
|
||||
case 1:
|
||||
filename = "BATON";
|
||||
break;
|
||||
case 2:
|
||||
filename = "TIME MACHINE";
|
||||
break;
|
||||
case 3:
|
||||
filename = "ARROW I";
|
||||
break;
|
||||
case 4:
|
||||
filename = "ARROW II";
|
||||
break;
|
||||
case 5:
|
||||
filename = "PULSAR 7";
|
||||
break;
|
||||
case 6:
|
||||
filename = "CIRCUS";
|
||||
break;
|
||||
default:
|
||||
error("mysteriousMenu: Unknown Game");
|
||||
}
|
||||
|
||||
int length;
|
||||
uint8_t *file = getFileNamed(*sf, *extent, &length, filename);
|
||||
|
||||
if (file != nullptr) {
|
||||
delete[] *sf;
|
||||
*sf = file;
|
||||
*extent = length;
|
||||
C64Rec rec = g_C64Registry[recindex - 1 + result];
|
||||
return decrunchC64(sf, extent, rec);
|
||||
} else {
|
||||
error("mysteriousMenu: Failed loading file %s", filename);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mysteriousMenu2(uint8_t **sf, size_t *extent, int recindex) {
|
||||
recindex = 6;
|
||||
|
||||
g_scott->output("This disk image contains five games. Select one.\n\n"
|
||||
"1. Feasibility Experiment\n"
|
||||
"2. The Wizard of Akyrz\n"
|
||||
"3. Perseus and Andromeda\n"
|
||||
"4. Ten Little Indians\n"
|
||||
"5. Waxworks");
|
||||
|
||||
g_scott->glk_request_char_event(_G(_bottomWindow));
|
||||
|
||||
event_t ev;
|
||||
int result = 0;
|
||||
do {
|
||||
g_scott->glk_select(&ev);
|
||||
if (ev.type == evtype_CharInput) {
|
||||
if (ev.val1 >= '1' && ev.val1 <= '5') {
|
||||
result = ev.val1 - '0';
|
||||
} else {
|
||||
g_scott->glk_request_char_event(_G(_bottomWindow));
|
||||
}
|
||||
}
|
||||
|
||||
if (g_vm->shouldQuit())
|
||||
return 0;
|
||||
} while (result == 0);
|
||||
|
||||
g_scott->glk_window_clear(_G(_bottomWindow));
|
||||
|
||||
const char *filename = nullptr;
|
||||
switch (result) {
|
||||
case 1:
|
||||
filename = "EXPERIMENT";
|
||||
break;
|
||||
case 2:
|
||||
filename = "WIZARD OF AKYRZ";
|
||||
break;
|
||||
case 3:
|
||||
filename = "PERSEUS";
|
||||
break;
|
||||
case 4:
|
||||
filename = "INDIANS";
|
||||
break;
|
||||
case 5:
|
||||
filename = "WAXWORKS";
|
||||
break;
|
||||
default:
|
||||
error("mysteriousMenu2: Unknown Game");
|
||||
}
|
||||
|
||||
int length;
|
||||
uint8_t *file = getFileNamed(*sf, *extent, &length, filename);
|
||||
|
||||
if (file != nullptr) {
|
||||
delete[] *sf;
|
||||
*sf = file;
|
||||
*extent = length;
|
||||
C64Rec rec = g_C64Registry[recindex - 1 + result];
|
||||
return decrunchC64(sf, extent, rec);
|
||||
} else {
|
||||
error("mysteriousMenu2: Failed loading file %s", filename);
|
||||
}
|
||||
}
|
||||
|
||||
int detectC64(uint8_t **sf, size_t *extent) {
|
||||
if (*extent > MAX_LENGTH || *extent < MIN_LENGTH)
|
||||
return 0;
|
||||
|
||||
Common::String md5 = g_vm->getGameMD5();
|
||||
int index = _G(_md5Index)[md5];
|
||||
if (g_C64Registry[index]._id == SAVAGE_ISLAND_C64) {
|
||||
return savageIslandMenu(sf, extent, index);
|
||||
} else if (g_C64Registry[index]._id == BATON_C64 && index == 0) {
|
||||
return mysteriousMenu(sf, extent, index);
|
||||
} else if (g_C64Registry[index]._id == FEASIBILITY_C64 && index == 6) {
|
||||
return mysteriousMenu2(sf, extent, index);
|
||||
}
|
||||
if (g_C64Registry[index]._type == TYPE_D64) {
|
||||
int newlength;
|
||||
uint8_t *largest_file = getLargestFile(*sf, *extent, &newlength);
|
||||
uint8_t *appendix = nullptr;
|
||||
int appendixlen = 0;
|
||||
|
||||
if (g_C64Registry[index]._appendFile != nullptr) {
|
||||
appendix = getFileNamed(*sf, *extent, &appendixlen, g_C64Registry[index]._appendFile);
|
||||
if (appendix == nullptr)
|
||||
error("detectC64(): Appending file failed");
|
||||
appendixlen -= 2;
|
||||
}
|
||||
|
||||
uint8_t *megabuf = new uint8_t[newlength + appendixlen];
|
||||
memcpy(megabuf, largest_file, newlength);
|
||||
if (appendix != nullptr) {
|
||||
memcpy(megabuf + newlength + g_C64Registry[index]._parameter, appendix + 2, appendixlen);
|
||||
newlength += appendixlen;
|
||||
}
|
||||
delete[] appendix;
|
||||
|
||||
if (largest_file) {
|
||||
*sf = megabuf;
|
||||
*extent = newlength;
|
||||
}
|
||||
delete[] largest_file;
|
||||
|
||||
} else if (g_C64Registry[index]._type == TYPE_T64) {
|
||||
uint8_t *file_records = *sf + 64;
|
||||
int number_of_records = READ_LE_UINT16(&(*sf)[36]);
|
||||
int offset = READ_LE_UINT16(&file_records[8]);
|
||||
int start_addr = READ_LE_UINT16(&file_records[2]);
|
||||
int end_addr = READ_LE_UINT16(&file_records[4]);
|
||||
int size;
|
||||
if (number_of_records == 1)
|
||||
size = *extent - offset;
|
||||
else
|
||||
size = end_addr - start_addr;
|
||||
uint8_t *first_file = new uint8_t[size + 2];
|
||||
memcpy(first_file + 2, *sf + offset, size);
|
||||
memcpy(first_file, file_records + 2, 2);
|
||||
*sf = first_file;
|
||||
*extent = size + 2;
|
||||
}
|
||||
return decrunchC64(sf, extent, g_C64Registry[index]);
|
||||
}
|
||||
|
||||
size_t copyData(size_t dest, size_t source, uint8_t** data, size_t dataSize, size_t bytesToMove) {
|
||||
if (source > dataSize || *data == nullptr)
|
||||
return 0;
|
||||
|
||||
size_t newSize = MAX(dest + bytesToMove, dataSize);
|
||||
uint8_t *megaBuf = new uint8_t[newSize];
|
||||
memcpy(megaBuf, *data, dataSize);
|
||||
memcpy(megaBuf + dest, *data + source, bytesToMove);
|
||||
delete[] *data;
|
||||
*data = megaBuf;
|
||||
return newSize;
|
||||
}
|
||||
|
||||
int decrunchC64(uint8_t **sf, size_t *extent, C64Rec record) {
|
||||
uint8_t *uncompressed = nullptr;
|
||||
_G(_fileLength) = *extent;
|
||||
|
||||
size_t decompressedLength = *extent;
|
||||
|
||||
uncompressed = new uint8_t[0xffff];
|
||||
|
||||
size_t result = 0;
|
||||
|
||||
for (int i = 1; i <= record._decompressIterations; i++) {
|
||||
/* We only send switches on the iteration specified by parameter */
|
||||
if (i == record._parameter && record._switches != nullptr) {
|
||||
result = unp64(_G(_entireFile), _G(_fileLength), uncompressed, &decompressedLength, record._switches);
|
||||
} else
|
||||
result = unp64(_G(_entireFile), _G(_fileLength), uncompressed, &decompressedLength, nullptr);
|
||||
if (result) {
|
||||
if (_G(_entireFile) != nullptr)
|
||||
delete[] _G(_entireFile);
|
||||
_G(_entireFile) = new uint8_t[decompressedLength];
|
||||
memcpy(_G(_entireFile), uncompressed, decompressedLength);
|
||||
_G(_fileLength) = decompressedLength;
|
||||
} else {
|
||||
delete[] uncompressed;
|
||||
uncompressed = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (uncompressed != nullptr)
|
||||
delete[] uncompressed;
|
||||
|
||||
for (int i = 0; i < NUMGAMES; i++) {
|
||||
if (_G(_games)[i]._gameID == record._id) {
|
||||
_G(_game) = &_G(_games)[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_G(_game)->_title == nullptr) {
|
||||
error("decrunchC64: Game not found");
|
||||
}
|
||||
|
||||
int offset;
|
||||
|
||||
DictionaryType dictype = getId(&offset);
|
||||
if (dictype != _G(_game)->_dictionary) {
|
||||
error("decrunchC64: Wrong game?");
|
||||
}
|
||||
|
||||
if (!tryLoading(*_G(_game), offset, 0)) {
|
||||
error("decrunchC64: Game could not be read");
|
||||
}
|
||||
|
||||
if (_G(_saveIslandAppendix1) != nullptr) {
|
||||
appendSIfiles(sf, extent);
|
||||
}
|
||||
|
||||
if (record._copySource != 0) {
|
||||
result = copyData(record._copyDest, record._copySource, sf, *extent, record._copySize);
|
||||
if (result) {
|
||||
*extent = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (CURRENT_GAME == CLAYMORGUE_C64 && record._copySource == 0x855) {
|
||||
result = copyData(0x1531a, 0x2002, sf, *extent, 0x2000);
|
||||
if (result) {
|
||||
*extent = result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(_G(_game)->_subType & MYSTERIOUS))
|
||||
sagaSetup(record._imgOffset);
|
||||
|
||||
return CURRENT_GAME;
|
||||
}
|
||||
|
||||
} // End of namespace Scott
|
||||
} // End of namespace Glk
|
||||
Reference in New Issue
Block a user