Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
/* 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/>.
*
*/
/*
* Copyright (c) 2002 - 2023 Magnus Lind.
*
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*/
#ifndef GLK_SCOTT_6502_EMU_H
#define GLK_SCOTT_6502_EMU_H
#include "glk/scott/types.h"
namespace Glk {
namespace Scott {
struct CpuCtx {
uint32_t _cycles;
uint16_t _pc;
uint8_t *_mem;
uint8_t _sp;
uint8_t _flags;
uint8_t _a;
uint8_t _x;
uint8_t _y;
};
int nextInst(CpuCtx *r);
} // End of namespace Scott
} // End of namespace Glk
#endif

View File

@@ -0,0 +1,235 @@
/* 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/>.
*
*/
/*
* Copyright (c) 2002 - 2023 Magnus Lind.
*
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*/
#include "common/util.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
int findSys(const byte *buf, int target) {
int outstart = -1;
int state = 1;
int i = 0;
/* skip link and line number */
buf += 4;
/* iAN: workaround for hidden sysline (1001 cruncher, CFB, etc)*/
if (buf[0] == 0) {
for (i = 5; i < 32; i++)
if (buf[i] == 0x9e && (((buf[i + 1] & 0x30) == 0x30) || ((buf[i + 2] & 0x30) == 0x30)))
break;
}
/* exit loop at line end */
while (i < 1000 && buf[i] != '\0') {
byte *sysEnd;
int c = buf[i];
switch (state) {
/* look for and consume sys token */
case 1:
if ((target == -1 && (c == 0x9e)) || c == target) {
state = 2;
}
break;
/* skip spaces and left parenthesis, if any */
case 2:
if (strchr(" (", c) != nullptr)
break;
// fallthrough
/* convert string number to int */
case 3:
outstart = (int)strtol((const char *)(buf + i), (char **)&sysEnd, 10);
if ((buf + i) == sysEnd) {
/* we got nothing */
outstart = -1;
} else {
c = *sysEnd;
if ((c >= 0xaa) && (c <= 0xae)) {
i = (int)strtol((char *)(sysEnd + 1), (char **)&sysEnd, 10);
switch (c) {
case 0xaa:
outstart += i;
break;
case 0xab:
outstart -= i;
break;
case 0xac:
outstart *= i;
break;
case 0xad:
if (i > 0)
outstart /= i;
break;
case 0xae:
c = outstart;
while (--i)
outstart *= c;
break;
}
} else if (c == 'E') {
i = (int)strtol((char *)(sysEnd + 1), (char **)&sysEnd, 10);
i++;
while (--i)
outstart *= 10;
}
}
state = 4;
break;
case 4:
break;
}
++i;
}
return outstart;
}
static void loadPrgData(byte mem[65536], uint8_t *data, size_t dataLength, LoadInfo *info) {
int len = MIN(65536 - info->_start, static_cast<int>(dataLength));
memcpy(mem + info->_start, data, (size_t)len);
info->_end = info->_start + len;
info->_basicVarStart = -1;
info->_run = -1;
if (info->_basicTxtStart >= info->_start && info->_basicTxtStart < info->_end) {
info->_basicVarStart = info->_end;
}
}
void loadData(uint8_t *data, size_t dataLength, byte mem[65536], LoadInfo *info) {
int load = data[0] + data[1] * 0x100;
info->_start = load;
loadPrgData(mem, data + 2, dataLength - 2, info);
}
int strToInt(const char *str, int *value) {
int status = 0;
do {
char *strEnd;
long lval;
/* base 0 is auto detect */
int base = 0;
if (*str == '\0') {
/* no string to parse */
status = 1;
break;
}
if (*str == '$') {
/* a $ prefix specifies base 16 */
++str;
base = 16;
}
lval = strtol(str, &strEnd, base);
if (*strEnd != '\0') {
/* there is garbage in the string */
status = 1;
break;
}
if (value != nullptr) {
/* all is well, set the out parameter */
*value = static_cast<int>(lval);
}
} while (0);
return status;
}
bool u32eq(const unsigned char *addr, uint32_t val)
{
return addr[3] == (val >> 24) &&
addr[2] == ((val >> 16) & 0xff) &&
addr[1] == ((val >> 8) & 0xff) &&
addr[0] == (val & 0xff);
}
bool u32eqmasked(const unsigned char *addr, uint32_t mask, uint32_t val)
{
uint32_t val1 = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
return (val1 & mask) == val;
}
bool u32eqxored(const unsigned char *addr, uint32_t xormask, uint32_t val)
{
uint32_t val1 = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
return (val1 ^ xormask) == val;
}
bool u16eqmasked(const unsigned char *addr, uint16_t mask, uint16_t val)
{
uint16_t val1 = addr[0] | (addr[1] << 8);
return (val1 & mask) == val;
}
bool u16eq(const unsigned char *addr, uint16_t val)
{
return addr[1] == (val >> 8) &&
addr[0] == (val & 0xff);
}
bool u16noteq(const unsigned char *addr, uint16_t val)
{
return addr[1] != (val >> 8) ||
addr[0] != (val & 0xff);
}
bool u16gteq(const unsigned char *addr, uint16_t val)
{
uint16_t val2 = addr[0] | (addr[1] << 8);
return val2 >= val;
}
bool u16lteq(const unsigned char *addr, uint16_t val)
{
uint16_t val2 = addr[0] | (addr[1] << 8);
return val2 <= val;
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,78 @@
/* 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/>.
*
*/
/*
* Copyright (c) 2002 - 2023 Magnus Lind.
*
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*/
#ifndef GLK_SCOTT_EXO_UTIL_H
#define GLK_SCOTT_EXO_UTIL_H
#include "glk/scott/types.h"
namespace Glk {
namespace Scott {
struct LoadInfo {
int _basicTxtStart; /* in */
int _basicVarStart; /* out */
int _run; /* out */
int _start; /* out */
int _end; /* out */
};
int findSys(const byte *buf, int target);
void loadData(uint8_t *data, size_t dataLength, byte mem[65536], LoadInfo *info);
int strToInt(const char *str, int *value);
bool u32eq(const unsigned char *addr, uint32_t val);
bool u16eq(const unsigned char *addr, uint16_t val);
bool u16gteq(const unsigned char *addr, uint16_t val);
bool u16lteq(const unsigned char *addr, uint16_t val);
bool u16noteq(const unsigned char *addr, uint16_t val);
bool u32eqmasked(const unsigned char *addr, uint32_t mask, uint32_t val);
bool u32eqxored(const unsigned char *addr, uint32_t ormask, uint32_t val);
bool u16eqmasked(const unsigned char *addr, uint16_t mask, uint16_t val);
} // End of namespace Scott
} // End of namespace Glk
#endif

View File

@@ -0,0 +1,53 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnActionPacker(UnpStr *unp) {
byte *mem;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x811, 0x018538A9) &&
u32eq(mem + 0x81d, 0xCEF7D0E8) &&
u32eq(mem + 0x82d, 0x0F9D0837) &&
u32eq(mem + 0x84b, 0x03D00120)) {
unp->_depAdr = 0x110;
unp->_forced = 0x811;
unp->_strMem = READ_LE_UINT16(&mem[0x848]);
unp->_fEndAf = 0x120;
unp->_retAdr = READ_LE_UINT16(&mem[0x863]);
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,94 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnByteBoiler(UnpStr *unp) {
byte *mem;
int q, p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x813, 0xE800F09D) &&
u32eq(mem + 0x818, 0x014E4CF7)) {
p = READ_LE_UINT16(&mem[0x811]);
if (u32eq(mem + p + 1, 0x02D0FAA5)) {
unp->_depAdr = 0x14e;
unp->_forced = 0x80b;
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x5c]);
unp->_endAdr = READ_LE_UINT16(&mem[p + 0x0e]);
unp->_endAdr++;
unp->_fStrAf = 0xfe;
unp->_idFlag = 1;
return;
}
}
}
/* CPX hack */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x80b, 0xA97800A2) &&
u32eq(mem + 0x815, 0x4C01E6D0)) {
q = READ_LE_UINT16(&mem[0x819]);
if (u32eq(mem + q + 3, 0xE800F09D) &&
u32eq(mem + q + 8, 0x014E4CF7)) {
p = READ_LE_UINT16(&mem[q + 1]);
if (u32eq(mem + p + 1, 0x02D0FAA5)) {
unp->_depAdr = 0x14e;
unp->_forced = 0x80b;
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x5c]);
unp->_endAdr = READ_LE_UINT16(&mem[p + 0x0e]);
unp->_endAdr++;
unp->_fStrAf = 0xfe;
unp->_idFlag = 1;
return;
}
}
}
}
/* SCS hack */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x813, 0xE800F09D) &&
u32eq(mem + 0x818, 0x01bf4CF7)) {
p = READ_LE_UINT16(&mem[0x811]);
if (u32eq(mem + p + 1, 0x02D0FAA5) &&
u32eq(mem + p + 0xdd, 0x014e4c01)) {
unp->_depAdr = 0x14e;
unp->_forced = 0x80b;
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x5c]);
unp->_endAdr = READ_LE_UINT16(&mem[p + 0x0e]);
unp->_endAdr++;
unp->_fStrAf = 0xfe;
unp->_idFlag = 1;
return;
}
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,135 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnCaution(UnpStr *unp) {
byte *mem;
if (unp->_idFlag)
return;
mem = unp->_mem;
/* quickpacker 1.0 sysless */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x801, 0xE67800A2) &&
u32eq(mem + 0x805, 0x07EDBD01) &&
u32eq(mem + 0x80d, 0x00284CF8) &&
u32eq(mem + 0x844, 0xAC00334C)) {
unp->_forced = 0x801;
unp->_depAdr = 0x28;
unp->_retAdr = READ_LE_UINT16(&mem[0x86b]);
unp->_endAdr = READ_LE_UINT16(&mem[0x85a]);
unp->_fStrAf = mem[0x863];
unp->_strAdC = EA_ADDFF | 0xffff;
unp->_idFlag = 1;
return;
}
}
/* quickpacker 2.x + sys */
if (unp->_depAdr == 0) {
if (u32eqmasked(mem + 0x80b, 0xf0ffffff, 0x60A200A0) &&
u32eq(mem + 0x80f, 0x0801BD78) &&
u32eq(mem + 0x813, 0xD0CA0095) &&
u32eq(mem + 0x81e, 0xD0C80291) &&
u32eq(mem + 0x817, 0x001A4CF8)) {
unp->_forced = 0x80b;
unp->_depAdr = 0x01a;
if (mem[0x80e] == 0x69) {
unp->_retAdr = READ_LE_UINT16(&mem[0x842]);
unp->_endAdr = READ_LE_UINT16(&mem[0x850]);
unp->_endAdr += 0x100;
unp->_fStrAf = 0x4f;
unp->_strAdC = 0xffff | EA_USE_Y;
unp->_idFlag = 1;
return;
} else if (mem[0x80e] == 0x6c) {
unp->_retAdr = READ_LE_UINT16(&mem[0x844]);
unp->_endAdr = READ_LE_UINT16(&mem[0x84e]);
unp->_endAdr++;
unp->_fStrAf = 0x4d;
unp->_idFlag = 1;
return;
}
}
}
/* strangely enough, sysless v2.0 depacker is at $0002 */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x83d, 0xAA004A20) &&
u32eq(mem + 0x801, 0xA27800A0) &&
u32eq(mem + 0x805, 0x080FBD55) &&
u32eq(mem + 0x809, 0xD0CA0095) &&
u32eq(mem + 0x80d, 0x00024CF8)) {
unp->_forced = 0x801;
unp->_depAdr = 0x2;
unp->_retAdr = READ_LE_UINT16(&mem[0x83b]);
unp->_endAdr = READ_LE_UINT16(&mem[0x845]);
unp->_endAdr++;
unp->_fStrAf = mem[0x849];
// unp->_StrAdC=0xffff;
unp->_idFlag = 1;
return;
}
}
/* same goes for v2.5 sysless, seems almost another packer */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x83b, 0xAA005520) &&
u32eq(mem + 0x801, 0x60A200A0) &&
u32eq(mem + 0x805, 0x0801BD78) &&
u32eq(mem + 0x809, 0xD0CA0095) &&
u32eq(mem + 0x80d, 0x00104CF8)) {
unp->_forced = 0x801;
unp->_depAdr = 0x10;
unp->_retAdr = READ_LE_UINT16(&mem[0x839]);
unp->_endAdr = READ_LE_UINT16(&mem[0x847]);
unp->_endAdr += 0x100;
unp->_fStrAf = 0x46;
unp->_strAdC = 0xffff | EA_USE_Y;
unp->_idFlag = 1;
return;
}
}
/* hardpacker */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x80d, 0x8534A978) &&
u32eq(mem + 0x811, 0xB9B3A001) &&
u32eq(mem + 0x815, 0x4C99081F) &&
u32eq(mem + 0x819, 0xF7D08803) &&
u32eq(mem + 0x81d, 0xB9034D4C)) {
unp->_forced = 0x80d;
unp->_depAdr = 0x34d;
unp->_retAdr = READ_LE_UINT16(&mem[0x87f]);
unp->_endAdr = READ_LE_UINT16(&mem[0x88d]);
unp->_fStrAf = 0x3ba;
unp->_strAdC = EA_ADDFF | 0xffff;
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,208 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnCCS(UnpStr *unp) {
byte *mem;
int p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x817, 0xB901E678) &&
u32eq(mem + 0x81b, 0xFD990831) &&
u32eq(mem + 0x8ff, 0xFEE60290) &&
u32eq(mem + 0x90f, 0x02903985)) {
if (unp->_info->_run == -1)
unp->_forced = 0x817;
unp->_depAdr = 0x0ff;
unp->_fEndAf = 0x2d;
unp->_endAdC = 0xffff;
unp->_retAdr = READ_LE_UINT16(&mem[0x8ed]);
if (unp->_retAdr == 0xa659) {
mem[0x8ec] = 0x2c;
unp->_retAdr = READ_LE_UINT16(&mem[0x8f0]);
}
unp->_idFlag = 1;
return;
}
}
/* derived from supercomp/eqseq */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x80b, 0x8C7800A0) &&
u32eq(mem + 0x812, 0x0099082F) &&
u32eq(mem + 0x846, 0x0DADF2D0) &&
u32eq(mem + 0x8c0, 0xF001124C)) {
if (unp->_info->_run == -1)
unp->_forced = 0x80b;
unp->_depAdr = 0x100;
unp->_endAdr = 0xae;
unp->_retAdr = READ_LE_UINT16(&mem[0x8f1]);
if (unp->_retAdr == 0xa659) {
mem[0x8f0] = 0x2c;
unp->_retAdr = READ_LE_UINT16(&mem[0x8f4]);
}
unp->_idFlag = 1;
return;
}
}
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x814, 0xB901E678) &&
u32eq(mem + 0x818, 0xFD990829) &&
u32eq(mem + 0x8a1, 0xFDA6FDB1) &&
u32eq(mem + 0x8a5, 0xFEC602D0)) {
if (unp->_info->_run == -1)
unp->_forced = 0x814;
unp->_depAdr = 0x0ff;
unp->_fEndBf = 0x39;
unp->_idFlag = 1;
return;
}
}
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x818, 0x2CB901E6) &&
u32eq(mem + 0x81c, 0x00FB9908) &&
u32eq(mem + 0x850, 0xFBB1C84A) &&
u32eq(mem + 0x854, 0xB1C81185)) {
if (unp->_info->_run == -1)
unp->_forced = 0x812;
unp->_depAdr = 0x0ff;
unp->_endAdr = 0xae;
unp->_idFlag = 1;
return;
}
}
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x818, 0x2CB901E6) &&
u32eq(mem + 0x81c, 0x00FB9908) &&
u32eq(mem + 0x851, 0xFBB1C812) &&
u32eq(mem + 0x855, 0xB1C81185)) {
if (unp->_info->_run == -1)
unp->_forced = 0x812;
unp->_depAdr = 0x0ff;
unp->_endAdr = 0xae;
unp->_idFlag = 1;
return;
}
}
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x82c, 0x018538A9) &&
u32eq(mem + 0x831, 0xFD990842) &&
u32eq(mem + 0x83e, 0x00FF4CF1) &&
u32eq(mem + 0x8a5, 0x50C651C6)) {
if (unp->_info->_run == -1)
unp->_forced = 0x822;
unp->_depAdr = 0x0ff;
unp->_fEndBf = 0x39;
unp->_retAdr = READ_LE_UINT16(&mem[0x8ea]);
unp->_idFlag = 1;
return;
}
}
if (unp->_depAdr == 0) {
if (u16eq(mem + 0x81a, 0x00A0) &&
(u32eq(mem + 0x820, 0xFB990837) ||
u32eq(mem + 0x824, 0xFB990837)) &&
u32eq(mem + 0x83b, 0xFD91FBB1) &&
u32eq(mem + 0x8bc, 0xEE00FC99)) {
if (unp->_info->_run == -1)
unp->_forced = 0x81a;
unp->_depAdr = 0x0ff;
unp->_fEndAf = 0x39;
unp->_endAdC = 0xffff;
unp->_retAdr = READ_LE_UINT16(&mem[0x8b3]);
unp->_idFlag = 1;
return;
}
}
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x812, 0xE67800A0) &&
u32eq(mem + 0x816, 0x0823B901) &&
u32eq(mem + 0x81a, 0xC800FD99) &&
u32eq(mem + 0x81e, 0xFF4CF7D0) &&
u32eq(mem + 0x885, 0xFDA6FDB1)) {
if (unp->_info->_run == -1)
unp->_forced = 0x812;
unp->_depAdr = 0x0ff;
// $2d is unreliable, Executer uses line number at $0803/4,
// which is read at $0039/3a by basic, as end address,
// then can set arbitrarily $2d/$ae pointers after unpack.
// unp->_fEndAf=0x2d;
unp->_endAdr = READ_LE_UINT16(&mem[0x803]);
unp->_endAdr++;
if (u32eq(mem + 0x87f, 0x4CA65920))
mem[0x87f] = 0x2c;
unp->_retAdr = READ_LE_UINT16(&mem[0x883]);
unp->_idFlag = 1;
return;
}
}
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x812, 0xE67800A0) &&
u32eq(mem + 0x816, 0x084CB901) &&
u32eq(mem + 0x81a, 0xA900FB99) &&
u32eq(mem + 0x848, 0x00FF4CE2)) {
if (unp->_info->_run == -1)
unp->_forced = 0x812;
unp->_depAdr = 0x0ff;
unp->_fEndAf = 0x2d;
unp->_endAdC = 0xffff;
unp->_idFlag = 1;
return;
}
}
/* Triad Hack */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x838, 0xB9080099) &&
u32eq(mem + 0x83f, 0xD0880816) &&
u32eq(mem + 0x8ff, 0xFEE60290) &&
u32eq(mem + 0x90f, 0x02903985)) {
if (unp->_info->_run == -1) {
for (p = 0x80b; p < 0x820; p++) {
if ((mem[p] & 0xa0) == 0xa0) {
unp->_forced = p;
break;
}
}
}
unp->_depAdr = 0x0ff;
unp->_fEndAf = 0x2d;
unp->_endAdC = 0xffff;
unp->_retAdr = READ_LE_UINT16(&mem[0x8ed]);
if (unp->_retAdr == 0xa659) {
mem[0x8ec] = 0x2c;
unp->_retAdr = READ_LE_UINT16(&mem[0x8f0]);
}
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,374 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnCruel(UnpStr *unp) {
byte *mem;
int q, p, strtmp = 0;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
if (mem[0x810] == 0xb9 &&
((*(unsigned int *)(mem + 0x813) & 0xfffffeff) == 0xC800FA99) &&
u16eq(mem + 0x818, 0x4CF7)) {
if (mem[0x814] == 0xFA) {
p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
if (u32eq(mem + p + 9, 0xC8071C99)) {
unp->_endAdr = READ_LE_UINT16(&mem[p + 2]); // mem[p + 2] | mem[p + 3] << 8;
unp->_depAdr = 0x100;
if (unp->_info->_run == -1)
unp->_forced = 0x80b;
unp->_fStrAf = 0xfc;
q = READ_LE_UINT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
if ((mem[q + 0x8e] == 0xc6) && (mem[q + 0x8f] == 0x01) &&
(mem[q + 0x93] == 0xe6) && (mem[q + 0x94] == 0x01)) {
mem[q + 0x90] = 0x2c;
}
/* retadr is not always at the same addr, but at least can't
be anything < $07e8
*/
// unp->_retAdr=0x7e8;
q = READ_LE_UINT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
if (mem[q + 0x3c] == 0x4c) {
/* v2.2/dynamix, v2.5/cross, v2.5/crest */
strtmp = *(unsigned short int *)(mem + q + 0x3d);
} else if (mem[q + 0x4a] == 0x4c) {
strtmp = *(unsigned short int *)(mem + q + 0x4b);
} else if (mem[q + 0x3f] == 0x4c) {
/* v2.2/oneway+scs, also hacked as cruel 2mhz 1.0 */
strtmp = *(unsigned short int *)(mem + q + 0x40);
} else {
/* todo: determine real retadr, for now a default seems ok */
strtmp = 0;
}
if (strtmp) {
if (strtmp >= unp->_retAdr) {
unp->_retAdr = strtmp;
} else { /* now search it... variable code here */
strtmp += p - *(unsigned short int *)(mem + 0x814);
for (q = strtmp; q < unp->_info->_end; q++) {
if ((mem[q] == 0xa9) || (mem[q] == 0x85)) {
q++;
continue;
}
if (mem[q] == 0x8d) {
q += 2;
continue;
}
if (mem[q] == 0x4c) {
unp->_retAdr = *(unsigned short int *)(mem + q + 1);
;
break;
}
}
}
}
}
} else if (mem[0x814] == 0xFB) {
/* not Cruel2 but MSCRUNCH by Marco/Taboo
v1.0 works only with some old AR cart (unless patched ;)
v1.5 is infact more common
*/
p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
if (u32eq(mem + p + 7, 0xC8071C99)) {
unp->_endAdr = READ_LE_UINT16(&mem[p + 3]); // mem[p + 3] | mem[p + 4] << 8;
unp->_depAdr = 0x100;
unp->_forced = 0x80b;
unp->_fStrAf = 0xfe;
if ((mem[p + 0x93] == 0x4c) && (mem[p + 0xa1] == 0x4c)) {
unp->_retAdr = READ_LE_UINT16(&mem[p + 0xa2]); // mem[p + 0xa2] | mem[p + 0xa3] << 8;
} else if ((mem[p + 0x8c] == 0x4c) && (mem[p + 0x94] == 0x4c)) {
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x95]); // mem[p + 0x95] | mem[p + 0x96] << 8;
} else if ((mem[p + 0x20] == 0x4c) && (mem[p + 0x28] == 0x4c)) {
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x29]); // mem[p + 0x29] | mem[p + 0x2a] << 8;
}
}
}
}
if (unp->_depAdr) {
unp->_idFlag = 1;
return;
}
}
/* MSCRUNCH 1.5 hack by Anubis */
if (unp->_depAdr == 0) {
if (mem[0x819] == 0x4c) {
p = READ_LE_UINT16(&mem[0x81a]); //mem[0x81a] | mem[0x81b] << 8;
if ((mem[p] == 0xa9) && (mem[p + 0x0f] == 0x30) &&
u32eq(mem + p + 0x13, 0xCA04009D) &&
u32eq(mem + p + 0x38, 0x01084C01)) {
q = READ_LE_UINT16(&mem[p + 0x1f]); // mem[p + 0x1f] | mem[p + 0x20] << 8;
if (u32eq(mem + q + 7, 0xC8071C99)) {
unp->_endAdr = READ_LE_UINT16(&mem[q + 3]); // mem[q + 3] | mem[q + 4] << 8;
unp->_depAdr = 0x100;
if (unp->_info->_run == -1)
unp->_forced = 0x819;
unp->_fStrAf = 0xfe;
unp->_retAdr = READ_LE_UINT16(&mem[q + 0xa2]); // mem[q + 0xa2] | mem[q + 0xa3] << 8;
}
}
}
}
/* fast cruel 4.x */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x80b, 0xE67800A0) &&
u32eq(mem + 0x813, 0xC8034099) &&
(u32eq(mem + 0x818, 0x03404cF7) ||
u32eq(mem + 0x818, 0x03b34cF7) ||
u32eq(mem + 0x818, 0x03db4cF7))) {
p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
if (u32eq(mem + p, 0xa75801c6)) {
p += 0x45;
q = READ_LE_UINT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
unp->_endAdr = READ_LE_UINT16(&mem[q + 2]); // mem[q + 2] | mem[q + 3] << 8;
unp->_depAdr = 0x340;
unp->_forced = 0x80b;
unp->_fStrAf = 0xfc;
unp->_idFlag = 1;
return;
}
}
}
/* Cruel 2.0 / (BB) packer header */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x837, 0x9D0845BD) &&
u32eq(mem + 0x84f, 0xE808039D) &&
u32eq(mem + 0x83b, 0xC9E803B7)) {
unp->_depAdr = READ_LE_UINT16(&mem[0x843]); // mem[0x843] | mem[0x844] << 8;
if (unp->_info->_run == -1)
unp->_forced = 0x80d;
unp->_retAdr = READ_LE_UINT16(&mem[0x868]); // mem[0x868] | mem[0x869] << 8;
unp->_endAdr = unp->_info->_end - 0x90;
unp->_strMem = 0x801;
unp->_idFlag = 1;
return;
}
if (u32eq(mem + 0x845, 0x03E04CF2) &&
u32eq(mem + 0x852, 0x9D0893BD) &&
u32eq(mem + 0x856, 0xD0E80803)) {
unp->_depAdr = READ_LE_UINT16(&mem[0x847]); // mem[0x847] | mem[0x848] << 8;
if (unp->_info->_run == -1)
unp->_forced = 0x80d;
unp->_retAdr = READ_LE_UINT16(&mem[0x869]); // mem[0x869] | mem[0x86a] << 8;
unp->_endAdr = unp->_info->_end - 0x90;
unp->_strMem = 0x801;
unp->_idFlag = 1;
return;
}
if (u32eq(mem + 0x841, 0x03B74CF5) &&
u32eq(mem + 0x84c, 0x9D089BBD) &&
u32eq(mem + 0x850, 0xD0E8080B)) {
unp->_depAdr = READ_LE_UINT16(&mem[0x843]); // mem[0x843] | mem[0x844] << 8;
if (unp->_info->_run == -1) {
unp->_forced = 0x811;
} else {
mem[0x808] = '5'; /* just to be safe, change sys for next layer */
mem[0x809] = '9'; /* this hdr leaves it as sys2065 */
}
unp->_retAdr = READ_LE_UINT16(&mem[0x868]); // mem[0x868] | mem[0x869] << 8; /* fixed $080b */
unp->_endAdr = unp->_info->_end - 0x90;
unp->_strMem = 0x801;
unp->_idFlag = 1;
return;
}
/* this is a totally useless header, cheers TCOM! */
if (u32eq(mem + 0x80b, 0x1BB900A0) &&
u32eq(mem + 0x80f, 0x03B79908) &&
u32eq(mem + 0x823, 0x039D0840)) {
unp->_depAdr = READ_LE_UINT16(&mem[0x819]); // mem[0x819] | mem[0x81a] << 8;
if (unp->_info->_run == -1)
unp->_forced = 0x80b;
unp->_retAdr = READ_LE_UINT16(&mem[0x83e]); // mem[0x83e] | mem[0x83f] << 8;
unp->_endAdr = unp->_info->_end - 0x3d;
unp->_strMem = 0x801;
unp->_idFlag = 1;
return;
}
}
/* Cruel 2.0 / (BB) packer sysless */
if (unp->_depAdr == 0) {
if (u32eqmasked(mem + 0x80b, 0x0000ffff, 0x000000A0) &&
u32eq(mem + 0x817, 0xC800CB99) &&
u32eq(mem + 0x81b, 0x004CF7D0) && mem[0x81f] == 1) {
p = READ_LE_UINT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
p += 0x31;
if ((mem[p + 4] == 0xb9) &&
u32eq(mem + p + 7, 0xC8072099)) {
unp->_forced = 0x80b;
unp->_depAdr = 0x100;
unp->_endAdr = READ_LE_UINT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
unp->_fStrAf = 0xfc;
/* patch: some version contain a zp cleaner sub at $01a2 */
if (u32eq(mem + p + 0xa6, 0x00A9CBA2) &&
u32eq(mem + p + 0xaa, 0xD0E80095)) {
mem[p + 0xa6] = 0x60;
}
/* patch: some version expects $01==#$34 already set from the header */
if (u32eq(mem + 0x811, 0xb9eaeaea)) {
mem[0x811] = 0xe6;
mem[0x812] = 0x01;
}
q = READ_LE_UINT16(&mem[p + 5]); // mem[p + 5] | mem[p + 6] << 8;
unp->_retAdr = 0x7e8;
if (mem[q + 0x6c] == 0x4c)
unp->_retAdr = READ_LE_UINT16(&mem[q + 0x6d]); // mem[q + 0x6d] | mem[q + 0x6e] << 8;
unp->_idFlag = 1;
return;
}
}
}
/* Cruel 2.1 / STA */
if (unp->_depAdr == 0) {
if (mem[0x80b] == 0xa0 && u32eq(mem + 0x817, 0xC800CB99) &&
u32eq(mem + 0x81b, 0x004CF7D0) && mem[0x81f] == 1) {
p = READ_LE_UINT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
p += 0x31;
if (mem[p + 6] == 0xb9 &&
u32eq(mem + p + 9, 0xC8072099)) {
unp->_forced = 0x80b;
unp->_depAdr = 0x100;
unp->_endAdr = READ_LE_UINT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
unp->_fStrAf = 0xfc;
q = READ_LE_UINT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
unp->_retAdr = 0x7e8;
if (mem[q + 0x6c] == 0x4c)
unp->_retAdr = READ_LE_UINT16(&mem[q + 0x6d]); // mem[q + 0x6d] | mem[q + 0x6e] << 8;
unp->_idFlag = 1;
return;
}
}
}
/* unknown cruel, jmp $00e9, found in Illusion/Random warez */
if (unp->_depAdr == 0) {
if (mem[0x810] == 0xb9 && u32eq(mem + 0x813, 0xC800e999) &&
u32eq(mem + 0x818, 0x00e94CF7)) {
p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
q = p - 0xed;
if (u32eq(mem + p, 0x13F01284) &&
u32eq(mem + q, 0xA9C8C8C8)) {
unp->_depAdr = 0xe9;
unp->_endAdr = READ_LE_UINT16(&mem[p + 0x13]); // mem[p + 0x13] | mem[p + 0x14] << 8;
unp->_retAdr = READ_LE_UINT16(&mem[q + 0x38]); // mem[q + 0x38] | mem[q + 0x39] << 8;
if (unp->_info->_run == -1)
unp->_forced = 0x80b;
unp->_fStrAf = 0xfc;
unp->_idFlag = 1;
return;
}
}
}
if (unp->_depAdr == 0) {
if (mem[0x810] == 0xb9 && u32eq(mem + 0x813, 0xC800ed99) &&
u32eq(mem + 0x818, 0x01004CF7)) {
p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
q = p - 0xed;
if (u32eq(mem + p, 0x01C60888) &&
u32eq(mem + q, 0xA9C8C8C8)) {
unp->_depAdr = 0x100;
unp->_endAdr = READ_LE_UINT16(&mem[p + 0x0f]); // mem[p + 0x0f] | mem[p + 0x10] << 8;
unp->_retAdr = READ_LE_UINT16(&mem[q + 0x38]); // mem[q + 0x38] | mem[q + 0x39] << 8;
if (unp->_info->_run == -1)
unp->_forced = 0x80b;
unp->_fStrAf = 0xfc;
unp->_idFlag = 1;
return;
}
}
}
/* cruel 1.2 / unknown 2059 */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x80b, 0xE67800A0) &&
u32eq(mem + 0x80f, 0x0803B901) &&
u32eq(mem + 0x813, 0xC800E399) &&
u32eq(mem + 0x817, 0x004CF7D0) &&
u32eq(mem + 0x90b, 0xC068FEC6)) {
unp->_depAdr = 0x100;
unp->_forced = 0x80b;
unp->_retAdr = READ_LE_UINT16(&mem[0x91c]); // mem[0x91c] | mem[0x91d] << 8;
unp->_endAdr = 0x2d;
unp->_fStrAf = 0xfc;
unp->_idFlag = 1;
return;
}
/* this was found in Agile and S451 cracks, Galleon's "Cruel+Search"
it's actually the real v1.0
*/
if (u32eq(mem + 0x80b, 0xE67800A0) &&
u32eq(mem + 0x80f, 0x0803B901) &&
u32eq(mem + 0x813, 0xC800E399) &&
u32eq(mem + 0x8c5, 0x011D4C04) &&
u32eq(mem + 0x90b, 0xB1486018)) {
unp->_depAdr = 0x100;
unp->_forced = 0x80b;
unp->_retAdr = READ_LE_UINT16(&mem[0x92d]); // mem[0x92d] | mem[0x92e] << 8;
unp->_endAdr = 0x2d;
unp->_fStrAf = 0xfc;
unp->_idFlag = 1;
return;
}
if (u32eq(mem + 0x80b, 0xE67800A0) &&
u32eq(mem + 0x80f, 0x0803B901) &&
u32eq(mem + 0x813, 0xC800E399) &&
u32eq(mem + 0x8b7, 0x011D4C04) &&
u32eq(mem + 0x8fc, 0xB1486018)) {
unp->_depAdr = 0x100;
unp->_forced = 0x80b;
unp->_retAdr = READ_LE_UINT16(&mem[0x91e]); // mem[0x91e] | mem[0x91f] << 8;
unp->_endAdr = 0x2d;
unp->_fStrAf = 0xfc;
unp->_idFlag = 1;
return;
}
}
/* TKC "proggy crueler 2.3" (and 2.5) */
if (unp->_depAdr == 0) {
if (mem[0x810] == 0xb9 && mem[0x819] == 0xa9 &&
u32eq(mem + 0x813, 0xC800fa99) &&
u32eq(mem + 0x822, 0x4CAF86AE)) {
p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
q = p - 0x100;
if (u32eq(mem + p + 0x0c, 0x20F7D0C8) &&
u32eq(mem + q, 0xA9C8C8C8)) {
unp->_depAdr = 0x100;
unp->_endAdr = READ_LE_UINT16(&mem[p + 0x02]); // mem[p + 0x02] | mem[p + 0x03] << 8;
unp->_retAdr = READ_LE_UINT16(&mem[q + 0x3f]); // mem[q + 0x3f] | mem[q + 0x40] << 8;
if (unp->_info->_run == -1)
unp->_forced = 0x80b;
unp->_fStrAf = 0xfc;
unp->_idFlag = 1;
return;
}
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,185 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnECA(UnpStr *unp) {
byte *mem;
int q, p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
// for(p=0x810;p<0x830;p+=0x4)
for (p = 0x80d; p < 0x830; p += 0x1) {
if (u32eq(mem + p + 0x08, (unsigned int)(0x2D9D0032 + p)) &&
u32eq(mem + p + 0x3a, 0x2a2a2a2a) &&
u32eq(mem + p + 0x0c, 0xF710CA00)) {
if (((*(unsigned int *)(mem + p + 0x00) & 0xf4fff000) == 0x8434A000) &&
u32eq(mem + p + 0x04, 0xBD05A201)) {
unp->_forced = p + 1;
} else if (((*(unsigned int *)(mem + p + 0x00) & 0xffffff00) == 0x04A27800) &&
u32eq(mem + p + 0x04, 0xBDE80186)) {
unp->_forced = p + 1;
} else if (((*(unsigned int *)(mem + p - 0x03) & 0xffffff00) == 0x04A27800) &&
u32eq(mem + p + 0x04, 0xBDE80186)) {
unp->_forced = p - 2;
} else if (u32eq(mem + p - 0x03, 0x8D00a978)) {
unp->_forced = p - 2;
}
}
if (!unp->_forced) {
if (u32eq(mem + p + 0x3a, 0x2a2a2a2a) &&
u32eq(mem + p + 0x02, 0x8534A978) &&
mem[p - 3] == 0xa0) {
unp->_forced = p - 3;
if (mem[p + 0x0d6] == 0x20 && mem[p + 0x0d7] == 0xe0 &&
mem[p + 0x0d8] == 0x03 && mem[p + 0x1da] == 0x5b &&
mem[p + 0x1e7] == 0x59) {
/* antiprotection :D */
mem[p + 0x0d6] = 0x4c;
mem[p + 0x0d7] = 0xae;
mem[p + 0x0d8] = 0xa7;
}
}
}
if (!unp->_forced) { /* FDT */
if (u32eq(mem + p + 0x3a, 0x2a2a2a2a) &&
u32eq(mem + p + 0x03, 0x8604A278) &&
u32eq(mem + p + 0x0a, 0x2D950842)) {
unp->_forced = p + 3;
}
}
if (!unp->_forced) {
/* decibel hacks */
if (u32eq(mem + p + 0x3a, 0x2a2a2a2a) &&
u32eq(mem + p + 0x00, 0x9D085EBD) &&
u32eq(mem + p - 0x06, 0x018534A9)) {
unp->_forced = p - 0x6;
}
}
if (unp->_forced) {
for (q = 0xd6; q < 0xde; q++) {
if (mem[p + q] == 0x20) {
if (u16eq(mem + p + q + 1, 0xa659) ||
u16eq(mem + p + q + 1, 0xff81) ||
u16eq(mem + p + q + 1, 0xe3bf) ||
u16eq(mem + p + q + 1, 0xe5a0) ||
u16eq(mem + p + q + 1, 0xe518)) {
mem[p + q] = 0x2c;
q += 2;
continue;
} else {
unp->_retAdr = READ_LE_UINT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
break;
}
}
if (mem[p + q] == 0x4c) {
unp->_retAdr = READ_LE_UINT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
break;
}
}
unp->_depAdr = READ_LE_UINT16(&mem[p + 0x30]); // mem[p + 0x30] | mem[p + 0x31] << 8;
// some use $2d, some $ae
for (q = 0xed; q < 0x108; q++) {
if (u32eq(mem + p + q, 0xA518F7D0)) {
unp->_endAdr = mem[p + q + 4];
// if(unp->_DebugP)
// printf("EndAdr from $%02x\n",unp->_endAdr);
break;
}
}
/*
if anything it's unpacked to $d000-efff, it will be copied
to $e000-ffff as last action in unpacker before starting.
0196 20 DA 01 JSR $01DA ; some have this jsr nopped, reloc doesn't
happen 0199 A9 37 LDA #$37 019b 85 01 STA $01 019d 58 CLI
019e 20 00 0D JSR $0D00 ; retaddr can be either here or following
01a1 4C AE A7 JMP $A7AE
01da B9 00 EF LDA $EF00,Y
01dd 99 00 FF STA $FF00,Y
01e0 C8 INY
01e1 D0 F7 BNE $01DA
01e3 CE DC 01 DEC $01DC
01e6 CE DF 01 DEC $01DF
01e9 AD DF 01 LDA $01DF
01ec C9 DF CMP #$DF ;<< not fixed, found as lower as $44 for
example 01ee D0 EA BNE $01DA 01f0 60 RTS Because of this,
$d000-dfff will be a copy of $e000-efff. So if $2d points to >= $d000,
SOMETIMES it's better save up to $ffff or: mem[$2d]|(mem[$2e]+$10)<<8
Still it's not a rule and I don't know exactly when.
17/06/09: Implemented but still experimental, so better check
extensively. use -v to know when it does the adjustments. 28/10/09:
whoops, was clearing ONLY $d000-dfff =)
*/
unp->_strMem = READ_LE_UINT16(&mem[p + 0x32]); // mem[p + 0x32] | mem[p + 0x33] << 8;
for (q = 0xcd; q < 0xd0; q++) {
if (u32eqmasked(mem + p + q, 0xffff00ff, 0xa9010020)) {
unp->_ecaFlg = READ_LE_UINT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
for (q = 0x110; q < 0x11f; q++) {
if (u32eq(mem + p + q, 0x99EF00B9) &&
mem[p + q + 0x12] == 0xc9) {
unp->_ecaFlg |= (mem[p + q + 0x13] - 0xf) << 24;
break;
}
}
break;
}
}
/* radwar hack has a BRK here, fffe/f used as IRQ/BRK vector */
if (mem[0x8e1] == 0) {
mem[0x8e1] = 0x6c;
mem[0x8e2] = 0xfe;
mem[0x8e3] = 0xff;
}
break;
}
}
if (unp->_depAdr) {
unp->_idFlag = 1;
return;
}
}
/* old packer, many old 1985 warez used this */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x81b, 0x018534A9) &&
u32eq(mem + 0x822, 0xAFC600A0) &&
u32eq(mem + 0x826, 0xB1082DCE) &&
u32eq(mem + 0x85b, 0x2A2A2A2A)) {
unp->_forced = 0x81b;
unp->_depAdr = 0x100;
unp->_strMem = READ_LE_UINT16(&mem[0x853]); // mem[0x853] | mem[0x854] << 8;
unp->_endAdr = mem[0x895];
unp->_retAdr = READ_LE_UINT16(&mem[0x885]); // mem[0x885] | mem[0x886] << 8;
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,177 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnExomizer(UnpStr *unp) {
byte *mem;
int q, p;
if (unp->_idFlag)
return;
mem = unp->_mem;
/* exomizer 3.x */
if (unp->_depAdr == 0) {
for (p = unp->_info->_end - 4; p > unp->_info->_start; p--) {
if (u32eq(mem + p, 0x100A8069) &&
u32eq(mem + p + 4, 0xD0FD060F) &&
mem[p - 6] == 0x4c && mem[p - 4] == 0x01) {
p -= 5;
q = 2;
if (mem[p - q] == 0x8a)
q++;
/* low byte of EndAdr, it's a lda $ff00,y */
if ((mem[p - q - 1] == mem[p - q - 3]) &&
(mem[p - q - 2] == mem[p - q])) { /* a0 xx a0 xx -> exomizer 3.0/3.01 */
unp->_exoFnd = 0x30;
} else { /* d0 c1 a0 xx -> exomizer 3.0.2, force +1 in start/end */
unp->_exoFnd = 0x32;
}
unp->_exoFnd |= (mem[p - q] << 8);
break;
}
}
if (unp->_exoFnd) {
unp->_depAdr = 0x100 | mem[p];
for (; p < unp->_info->_end; p++) {
if (u32eq(mem + p, 0x7d010020))
break;
}
for (; p < unp->_info->_end; p++) {
if (mem[p] == 0x4c) {
unp->_retAdr = 0;
if ((unp->_retAdr = READ_LE_UINT16(&mem[p + 1])) >= 0x200) {
break;
} else { /* it's a jmp $01xx, goto next */
p++;
p++;
}
}
}
if (unp->_info->_run == -1) {
p = unp->_info->_start;
q = p + 0x10;
for (; p < q; p++) {
if ((mem[p] == 0xba) && (mem[p + 1] == 0xbd)) {
unp->_forced = p;
break;
}
}
for (q = p - 1; q >= unp->_info->_start; q--) {
if (mem[q] == 0xe6)
unp->_forced = q;
if (mem[q] == 0xa0)
unp->_forced = q;
if (mem[q] == 0x78)
unp->_forced = q;
}
}
}
}
/* exomizer 1.x/2.x */
if (unp->_depAdr == 0) {
for (p = unp->_info->_end - 4; p > unp->_info->_start; p--) {
if (((u32eq(mem + p, 0x4CF7D088) &&
u32eq(mem + p - 0x0d, 0xD034C0C8)) ||
(u32eq(mem + p, 0x4CA7A438) &&
u32eq(mem + p - 0x0c, 0x799FA5AE)) ||
(u32eq(mem + p, 0x4CECD08A) &&
u32eq(mem + p - 0x13, 0xCECA0EB0)) ||
(u32eq(mem + p, 0x4C00A0D3) &&
u32eq(mem + p - 0x04, 0xD034C0C8)) ||
(u32eq(mem + p, 0x4C00A0D2) &&
u32eq(mem + p - 0x04, 0xD034C0C8))) &&
mem[p + 5] == 1) {
p += 4;
unp->_exoFnd = 1;
break;
} else if (((u32eq(mem + p, 0x8C00A0d2) &&
u32eq(mem + p - 0x04, 0xD034C0C8)) ||
(u32eq(mem + p, 0x8C00A0d3) &&
u32eq(mem + p - 0x04, 0xD034C0C8)) ||
(u32eq(mem + p, 0x8C00A0cf) &&
u32eq(mem + p - 0x04, 0xD034C0C8))) &&
mem[p + 6] == 0x4c && mem[p + 8] == 1) {
p += 7;
unp->_exoFnd = 1;
break;
}
}
if (unp->_exoFnd) {
unp->_depAdr = 0x100 | mem[p];
if (unp->_depAdr >= 0x134 && unp->_depAdr <= 0x14a /*0x13e*/) {
for (p = unp->_info->_end - 4; p > unp->_info->_start;
p--) { /* 02 04 04 30 20 10 80 00 */
if (u32eq(mem + p, 0x30040402))
break;
}
} else {
// exception for exo v1.x, otherwise add 8 to the counter and
// scan backward from here
if (unp->_depAdr != 0x143)
p += 0x08;
else
p -= 0xb8;
}
for (; p > unp->_info->_start; p--) {
// incredibly there can be a program starting at $4c00 :P
if ((mem[p] == 0x4c) && (mem[p - 1] != 0x4c) && (mem[p - 2] != 0x4c)) {
unp->_retAdr = 0;
if ((unp->_retAdr = READ_LE_UINT16(&mem[p + 1])) >= 0x200) {
break;
}
}
}
if (unp->_info->_run == -1) {
p = unp->_info->_start;
q = p + 0x10;
for (; p < q; p++) {
if ((mem[p] == 0xba) && (mem[p + 1] == 0xbd)) {
unp->_forced = p;
break;
}
}
for (q = p - 1; q >= unp->_info->_start; q--) {
if (mem[q] == 0xe6)
unp->_forced = q;
if (mem[q] == 0xa0)
unp->_forced = q;
if (mem[q] == 0x78)
unp->_forced = q;
}
}
}
}
if (unp->_depAdr != 0) {
unp->_idFlag = 1;
return;
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,247 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnExpert(UnpStr *unp) {
byte *mem;
int q, p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
for (q = 0x81b; q < 0x81d; q++) {
if (u32eq(mem + q + 0x00, 0x852FA978) &&
u32eq(mem + q + 0x04, 0x8534A900) &&
u32eq(mem + q + 0x14, 0x03860286)) {
for (p = 0x900; p < 0xfff0; p++) {
if (u32eq(mem + p + 1, 0x00084C9A) &&
u32eq(mem + p - 4, 0xA2058604)) {
if (unp->_info->_run == -1) {
unp->_forced = q;
unp->_info->_run = q;
}
q = 0x100 + mem[p] + 1;
if (q != 0x100) {
unp->_depAdr = q;
}
}
}
break;
}
}
if (unp->_depAdr) {
unp->_rtiFrc = 1;
if (u32eq(mem + 0x835, 0x6E8D48A9)) {
p = 0;
if (u32eq(mem + 0x92c, 0x4902B100)) {
if (!unp->_idOnly) {
p = 0x876;
mem[p] = 0x00; /* 1st anti hack */
p = mem[0x930];
}
} else if (u32eq(mem + 0x92f, 0x4902B100)) {
if (!unp->_idOnly) {
p = 0x873;
mem[p] = 0xa9; /* 1st anti hack */
mem[p + 1] = 0x02;
p = mem[0x933];
}
}
if (p && !unp->_idOnly) {
p |= (p << 24) | (p << 16) | (p << 8);
for (q = 0x980; q < 0xfff0; q++) {
if (((mem[q] ^ (p & 0xff)) == 0xac) &&
((mem[q + 3] ^ (p & 0xff)) == 0xc0) &&
u32eqxored(mem + q + 7, (unsigned int)p, 0xC001F2AC)) {
mem[q + 0x06] = (p & 0xff); /* 2nd anti hack */
mem[q + 0x0d] = (p & 0xff);
break;
}
}
}
}
}
}
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x81b, 0x2FA9D878) &&
u32eq(mem + 0x82d, 0x0873BDB0)) {
for (p = 0x900; p < 0xfff0; p++) {
if (u32eq(mem + p, 0xA2F3D0CA) &&
mem[p + 0x05] == 0x4c) {
q = READ_LE_UINT16(&mem[p + 0x06]); // mem[p + 0x06] | mem[p + 0x07] << 8;
if (q != 0x100) {
unp->_depAdr = q;
break;
}
}
}
if (unp->_depAdr) {
unp->_rtiFrc = 1;
unp->_forced = 0x81b;
}
}
}
/* 2.9 Expert User Club version, found in
BloodMoney/HTL & SWIV/Inceria
*/
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x81b, 0x8C00A078) &&
u32eq(mem + 0x831, 0x05860485) &&
u32eq(mem + 0x998, 0x00084C9A)) {
p = mem[0x919];
q = p << 24 | p << 16 | p << 8 | p;
for (p = 0x900; p < 0xfff0; p++) {
if (((*(unsigned int *)(mem + p) ^ (unsigned int)q) == 0xA2F3D0CA) &&
((mem[p + 0x05] ^ (q & 0xff)) == 0x4c)) {
q = (mem[p + 0x06] ^ (q & 0xff)) | (mem[p + 0x07] ^ (q & 0xff)) << 8;
if (q != 0x100) {
unp->_depAdr = q;
break;
}
}
}
if (unp->_depAdr) {
unp->_rtiFrc = 1;
unp->_forced = 0x81b;
}
}
}
/* sys2070 A.S.S. */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x817, 0x00852FA9) &&
u32eq(mem + 0x823, 0x05860485) &&
u32eq(mem + 0x9a0, 0x00084C9A)) {
p = mem[0x923];
q = p << 24 | p << 16 | p << 8 | p;
for (p = 0x900; p < 0xfff0; p++) {
if (((*(unsigned int *)(mem + p) ^ (unsigned int)q) == 0xA2F3D0CA) &&
((mem[p + 0x05] ^ (q & 0xff)) == 0x4c)) {
q = (mem[p + 0x06] ^ (q & 0xff)) | (mem[p + 0x07] ^ (q & 0xff)) << 8;
if (q != 0x100) {
unp->_depAdr = q;
break;
}
}
}
if (unp->_depAdr) {
unp->_rtiFrc = 1;
unp->_forced = 0x81b;
}
}
}
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x81b, 0x7FA978D8) ||
u32eq(mem + 0x81b, 0x7FA9D878) ||
u32eq(mem + 0x816, 0x7FA978D8)) {
for (p = 0x900; p < 0xfff0; p++) {
if (u32eq(mem + p, 0xA2F3D0CA) &&
mem[p + 0x05] == 0x4c) {
q = READ_LE_UINT16(&mem[p + 0x06]); // mem[p + 0x06] | mem[p + 0x07] << 8;
if (q != 0x100) {
unp->_depAdr = q;
break;
}
}
}
if (unp->_depAdr) {
unp->_rtiFrc = 1;
if (u32eq(mem + 0x816, 0x7FA978D8)) {
q = 0x816;
if (!unp->_idOnly) {
for (p = 0x900; p < 0xfff0; p++) {
if (u32eq(mem + p, 0xE0A9F0A2) &&
u32eq(mem + p + 4, 0xE807135D) &&
mem[p + 0x8] == 0xd0) {
mem[p + 0x1] = 0x00;
mem[p + 0x3] = 0x98;
memset(mem + p + 4, 0xea, 6);
break;
}
}
}
} else {
q = 0x81b;
if (!unp->_idOnly) {
for (p = 0x900; p < 0xfff0; p++) {
if (u32eq(mem + p, 0xCA08015D) &&
u32eq(mem + p + 4, 0xF8D003E0) &&
mem[p + 0xa] == 0xd0) {
p += 0xa;
mem[p] = 0x24;
break;
}
}
}
}
if (unp->_info->_run == -1) {
unp->_forced = q;
unp->_info->_run = q;
}
}
}
}
if (unp->_depAdr == 0) {
q = 0x81b;
if (u32eq(mem + q + 0x00, 0x852FA978) &&
u32eq(mem + q + 0x04, 0x8534A900) &&
u32eq(mem + q + 0x14, 0x03860286) &&
u32eq(mem + q + 0x4f, 0xA200594C) &&
u32eq(mem + q + 0xad, 0x2000124C)) {
unp->_forced = q;
unp->_info->_run = q;
unp->_depAdr = 0x12;
unp->_rtiFrc = 1;
}
}
/* expert 2.11 (sys2074) & unknown sys2061 */
if (unp->_depAdr == 0) {
for (q = 0x80d; q < 0x820; q++) {
if (u32eq(mem + q + 0x00, 0x852FA978) &&
u32eq(mem + q + 0x04, 0x8534A900) &&
u32eq(mem + q + 0x13, 0x03840284) &&
u32eq(mem + q + 0x4f, 0x084C003A) &&
u32eq(mem + q + 0xad, 0x00AA2048)) {
unp->_forced = q;
unp->_info->_run = q;
unp->_depAdr = 0x100 + mem[q + 0x17a] + 1;
break;
}
}
if (unp->_depAdr != 0) {
unp->_rtiFrc = 1;
}
}
if (unp->_depAdr != 0) {
unp->_idFlag = 1;
return;
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,125 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnMasterCompressor(UnpStr *unp) {
byte *mem;
int p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
for (p = 0x80d; p < 0x880; p++) {
if (u32eqmasked(mem + p + 0x005, 0x00ffffff, 0x00BDD2A2) &&
u32eq(mem + p + 0x00a, 0xE000F99D) &&
u32eq(mem + p + 0x017, 0xCAEDD0CA) &&
u32eq(mem + p + 0x031, 0x84C82E86) &&
u32eqmasked(mem + p + 0x035, 0x0000ffff, 0x00004C2D) &&
u32eq(mem + p + 0x134, 0xDBD0FFE6)) {
if (/*mem[p]==0x78&&*/ mem[p + 1] == 0xa9 &&
u32eq(mem + p + 0x003, 0xD2A20185)) {
unp->_depAdr = READ_LE_UINT16(&mem[p + 0x37]);
unp->_forced = p + 1;
if (mem[p + 0x12b] == 0x020) // jsr $0400, unuseful fx
mem[p + 0x12b] = 0x2c;
} else if (u32eq(mem + p, 0xD024E0E8)) {
/* HTL version */
unp->_depAdr = READ_LE_UINT16(&mem[p + 0x37]);
unp->_forced = 0x840;
}
if (unp->_depAdr) {
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x13e]);
unp->_endAdr = 0x2d;
unp->_fStrBf = unp->_endAdr;
unp->_idFlag = 1;
return;
}
}
}
}
if (unp->_depAdr == 0) {
for (p = 0x80d; p < 0x880; p++) {
if (u32eqmasked(mem + p + 0x005, 0x00ffffff, 0x00BDD2A2) &&
u32eq(mem + p + 0x00a, 0xE000F99D) &&
u32eq(mem + p + 0x017, 0xCAEDD0CA) &&
u32eq(mem + p + 0x031, 0x84C82E86) &&
u32eqmasked(mem + p + 0x035, 0x0000ffff, 0x00004C2D) &&
u32eq(mem + p + 0x12d, 0xe2D0FFE6)) {
if (mem[p + 1] == 0xa9 &&
u32eq(mem + p + 0x003, 0xD2A20185)) {
unp->_depAdr = READ_LE_UINT16(&mem[p + 0x37]);
unp->_forced = p + 1;
}
if (unp->_depAdr) {
if (mem[p + 0x136] == 0x4c)
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x137]);
else if (mem[p + 0x13d] == 0x4c)
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x13e]);
unp->_endAdr = 0x2d;
unp->_fStrBf = unp->_endAdr;
unp->_idFlag = 1;
return;
}
}
}
}
if (unp->_depAdr == 0) {
p = 0x812;
if (u32eq(mem + p + 0x000, 0xE67800A0) &&
u32eq(mem + p + 0x004, 0x0841B901) &&
u32eq(mem + p + 0x008, 0xB900FA99) &&
u32eq(mem + p + 0x00c, 0x34990910)) {
unp->_depAdr = 0x100;
unp->_forced = p;
unp->_retAdr = READ_LE_UINT16(&mem[0x943]); // mem[0x943] | mem[0x944] << 8;
unp->_endAdr = 0x2d;
unp->_fStrBf = unp->_endAdr;
unp->_idFlag = 1;
return;
}
}
/* Fred/Channel4 hack */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x811, 0xA9A98078) &&
u32eq(mem + 0x815, 0x85EE8034) &&
u32eq(mem + 0x819, 0x802DA201) &&
u32eq(mem + 0x882, 0x01004C2D)) {
unp->_depAdr = 0x100;
unp->_forced = 0x811;
unp->_retAdr = READ_LE_UINT16(&mem[0x98b]); // mem[0x98b] | mem[0x98c] << 8;
if (unp->_retAdr < 0x800)
unp->_rtAFrc = 1;
unp->_endAdr = 0x2d;
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,82 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnMegabyte(UnpStr *unp) {
byte *mem;
int p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
p = 0;
if (mem[0x816] == 0x4c)
p = READ_LE_UINT16(&mem[0x817]); // mem[0x817] | mem[0x818] << 8;
else if (unp->_info->_run == 0x810 && mem[0x814] == 0x4c &&
u32eqmasked(mem + 0x810, 0xffff00ff, 0x018500A9))
p = READ_LE_UINT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
if (p) {
if (mem[p + 0] == 0x78 && mem[p + 1] == 0xa2 &&
mem[p + 3] == 0xa0 &&
u32eq(mem + p + 0x05, 0x15841486) &&
u32eq(mem + p + 0x1d, 0x03804CF7)) {
unp->_depAdr = 0x380;
unp->_endAdr = READ_LE_UINT16(&mem[p + 0x55]); // mem[p + 0x55] | mem[p + 0x56] << 8;
unp->_endAdr++;
unp->_strMem = 0x801;
unp->_retAdr = 0x801; /* usually it just runs */
unp->_idFlag = 1;
return;
}
}
}
if (unp->_depAdr == 0) {
p = 0;
if (mem[0x81a] == 0x4c &&
u32eqmasked(mem + 0x816, 0xffff00ff, 0x018500A9))
p = READ_LE_UINT16(&mem[0x81b]); // mem[0x81b] | mem[0x81c] << 8;
if (p) {
if (mem[p + 0] == 0x78 && mem[p + 1] == 0xa2 &&
mem[p + 3] == 0xa0 &&
u32eq(mem + p + 0x05, 0x15841486) &&
u32eq(mem + p + 0x1d, 0x03844CF7)) {
unp->_depAdr = 0x384;
unp->_forced = 0x816;
unp->_endAdr = READ_LE_UINT16(&mem[p + 0x59]); // mem[p + 0x59] | mem[p + 0x5a] << 8;
unp->_endAdr++;
unp->_strMem = 0x801;
unp->_retAdr = 0x801; /* usually it just runs */
unp->_idFlag = 1;
return;
}
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,194 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnPuCrunch(UnpStr *unp) {
byte *mem;
int q, p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
if (mem[0x80d] == 0x78 &&
u32eq(mem + 0x813, 0x34A20185) &&
u32eq(mem + 0x817, 0x9D0842BD) &&
u32eq(mem + 0x81b, 0xD0CA01FF) &&
u32eq(mem + 0x83d, 0x4CEDD088)) {
for (p = 0x912; p < 0x938; p++) {
if (u32eq(mem + p, 0x2D85FAA5) &&
u32eq(mem + p + 4, 0x2E85FBA5)) {
unp->_endAdr = 0xfa;
unp->_strMem = READ_LE_UINT16(&mem[0x879]); // mem[0x879] | mem[0x87a] << 8;
unp->_depAdr = READ_LE_UINT16(&mem[0x841]); // mem[0x841] | mem[0x842] << 8;
unp->_retAdr = READ_LE_UINT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
unp->_forced = 0x80d;
break;
}
}
} else if (mem[0x80d] == 0x78 &&
u32eq(mem + 0x81a, 0x10CA4B95) &&
u32eq(mem + 0x81e, 0xBD3BA2F8) &&
u32eq(mem + 0x847, 0x4CEDD088)) {
for (p = 0x912; p < 0x938; p++) {
if (u32eq(mem + p, 0x2D85FAA5) &&
u32eq(mem + p + 4, 0x2E85FBA5)) {
unp->_endAdr = 0xfa;
unp->_strMem = READ_LE_UINT16(&mem[p + 0x88a]); // mem[0x88a] | mem[0x88b] << 8;
unp->_depAdr = READ_LE_UINT16(&mem[p + 0x84b]); // mem[0x84b] | mem[0x84c] << 8;
unp->_retAdr = READ_LE_UINT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
unp->_forced = 0x80d;
break;
}
}
} else if (mem[0x80d] == 0x78 &&
u32eq(mem + 0x811, 0x85AAA901) &&
u32eq(mem + 0x81d, 0xF69D083C) &&
u32eq(mem + 0x861, 0xC501C320) &&
u32eq(mem + 0x839, 0x01164CED)) {
unp->_endAdr = 0xfa;
unp->_strMem = READ_LE_UINT16(&mem[0x840]); // mem[0x840] | mem[0x841] << 8;
unp->_depAdr = 0x116;
unp->_retAdr = READ_LE_UINT16(&mem[0x8df]); // mem[0x8df] | mem[0x8e0] << 8;
unp->_forced = 0x80d;
} else if (mem[0x80d] == 0x78 &&
u32eq(mem + 0x811, 0x85AAA901) &&
u32eq(mem + 0x81d, 0xF69D083C) &&
u32eq(mem + 0x861, 0xC501C820) &&
u32eq(mem + 0x839, 0x01164CED)) {
unp->_endAdr = 0xfa;
unp->_strMem = READ_LE_UINT16(&mem[0x840]); // mem[0x840] | mem[0x841] << 8;
unp->_depAdr = 0x116;
if (mem[0x8de] == 0xa9) {
unp->_retAdr = READ_LE_UINT16(&mem[0x8e1]); // mem[0x8e1] | mem[0x8e2] << 8;
if ((unp->_retAdr == 0xa871) && (mem[0x8e0] == 0x20) &&
(mem[0x8e3] == 0x4c)) {
mem[0x8e0] = 0x2c;
unp->_retAdr = READ_LE_UINT16(&mem[0x8e4]); // mem[0x8e4] | mem[0x8e5] << 8;
}
} else {
unp->_retAdr = READ_LE_UINT16(&mem[0x8df]); // mem[0x8df] | mem[0x8e0] << 8;
}
unp->_forced = 0x80d;
} else {
/* unknown old/hacked pucrunch ? */
for (p = 0x80d; p < 0x820; p++) {
if (mem[p] == 0x78) {
q = p;
for (; p < 0x824; p++) {
if (u32eqmasked(mem + p, 0xf0ffffff, 0xF0BD53A2) &&
u32eq(mem + p + 4, 0x01FF9D08) &&
u32eq(mem + p + 8, 0xA2F7D0CA)) {
unp->_forced = q;
q = mem[p + 3] & 0xf; /* can be $f0 or $f2, q&0x0f as offset */
p = READ_LE_UINT16(&mem[p + 0xe]); // mem[p + 0xe] | mem[p + 0xf] << 8;
if (mem[p - 2] == 0x4c && mem[p + 0xa0 + q] == 0x85) {
unp->_depAdr = READ_LE_UINT16(&mem[p - 1]); // mem[p - 1] | mem[p] << 8;
unp->_strMem = READ_LE_UINT16(&mem[p + 4]); // mem[p + 4] | mem[p + 5] << 8;
unp->_endAdr = 0xfa;
p += 0xa2;
q = p + 8;
for (; p < q; p++) {
if (u32eq(mem + p, 0x2D85FAA5) &&
mem[p + 9] == 0x4c) {
unp->_retAdr = READ_LE_UINT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
break;
}
}
}
}
}
}
}
}
/* various old/hacked pucrunch */
/* common pattern, variable pos from 0x79 to 0xd1
90 ?? C8 20 ?? 0? 85 ?? C9 ?0 90 0B A2 0? 20 ?? 0? 85 ?? 20 ?? 0? A8 20 ??
0? AA BD ?? 0? E0 20 90 0? 8A (A2 03) not always 20 ?? 02 A6
?? E8 20 F9
*/
if (unp->_depAdr == 0) {
unp->_idFlag = 0;
for (q = 0x70; q < 0xff; q++) {
if (u32eqmasked(mem + 0x801 + q, 0xFFFF00FF, 0x20C80090) &&
u32eqmasked(mem + 0x801 + q + 8, 0xFFFF0FFF,
0x0B9000C9) &&
u32eqmasked(mem + 0x801 + q + 12, 0x00FFF0FF,
0x002000A2) &&
u32eqmasked(mem + 0x801 + q + 30, 0xF0FFFFFf,
0x009020E0)) {
unp->_idFlag = 385;
break;
}
}
if (unp->_idFlag) {
for (p = 0x801 + q + 34; p < 0x9ff; p++) {
if (u32eq(mem + p, 0x00F920E8)) {
for (; p < 0x9ff; p++) {
if (mem[p] == 0x4c) {
unp->_retAdr = READ_LE_UINT16(&mem[p + 1]);
if (unp->_retAdr > 0x257)
break;
}
}
break;
}
}
for (p = 0; p < 0x40; p++) {
if (unp->_info->_run == -1)
if (unp->_forced == 0) {
if (mem[0x801 + p] == 0x78) {
unp->_forced = 0x801 + p;
unp->_info->_run = unp->_forced;
}
}
if (u32eq(mem + 0x801 + p, 0xCA00F69D) &&
mem[0x801 + p + 0x1b] == 0x4c) {
q = 0x801 + p + 0x1c;
unp->_depAdr = READ_LE_UINT16(&mem[q]);
q = 0x801 + p - 2;
p = READ_LE_UINT16(&mem[q]);
if ((mem[p + 3] == 0x8d) && (mem[p + 6] == 0xe6)) {
unp->_strMem = READ_LE_UINT16(&mem[p + 4]);
}
break;
}
}
unp->_endAdr = 0xfa; // some hacks DON'T xfer fa/b to 2d/e
unp->_idFlag = 1;
}
}
if (unp->_depAdr) {
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,72 @@
/* 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/>.
*
*/
#include "glk/scott/unp64/unp64.h"
namespace Glk {
namespace Scott {
void scnECA(UnpStr *unp);
void scnExpert(UnpStr *unp);
void scnCruel(UnpStr *unp);
void scnPuCrunch(UnpStr *unp);
void scnByteBoiler(UnpStr *unp);
void scnMasterCompressor(UnpStr *unp);
void scnTCScrunch(UnpStr *unp);
void scnTBCMultiComp(UnpStr *unp);
void scnXTC(UnpStr *unp);
void scnCCS(UnpStr *unp);
void scnMegabyte(UnpStr *unp);
void scnSection8(UnpStr *unp);
void scnCaution(UnpStr *unp);
void scnActionPacker(UnpStr *unp);
void scnExomizer(UnpStr *unp);
Scnptr g_scanFunc[] = {
scnECA,
scnExpert,
scnCruel,
scnPuCrunch,
scnByteBoiler,
scnMasterCompressor,
scnTCScrunch,
scnTBCMultiComp,
scnXTC,
scnCCS,
scnMegabyte,
scnSection8,
scnCaution,
scnActionPacker,
scnExomizer
};
void scanners(UnpStr* unp) {
int x, y;
y = sizeof(g_scanFunc) / sizeof(*g_scanFunc);
for (x = 0; x < y; x++) {
(g_scanFunc[x])(unp);
if (unp->_idFlag)
break;
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,103 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnSection8(UnpStr *unp) {
byte *mem;
int p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
for (p = 0x810; p <= 0x828; p++) {
if (u32eq(mem + p, (unsigned int)(0x00BD00A2 + (((p & 0xff) + 0x11) << 24))) &&
u32eq(mem + p + 0x04, 0x01009D08) &&
u32eq(mem + p + 0x10, 0x34A97801) &&
u32eq(mem + p + 0x6a, 0xB1017820) &&
u32eq(mem + p + 0x78, 0x017F20AE)) {
unp->_depAdr = 0x100;
break;
}
}
if (unp->_depAdr) {
if (unp->_info->_run == -1)
unp->_forced = p;
unp->_strMem = mem[p + 0x47] | mem[p + 0x4b] << 8;
unp->_retAdr = READ_LE_UINT16(&mem[p + 0x87]); // mem[p + 0x87] | mem[p + 0x88] << 8;
if (unp->_retAdr == 0xf7) {
unp->_retAdr = 0xa7ae;
mem[p + 0x87] = 0xae;
mem[p + 0x88] = 0xa7;
}
unp->_endAdr = 0xae;
unp->_idFlag = 1;
return;
}
}
/* Crackman variant? */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x827, 0x38BD00A2) &&
u32eq(mem + 0x82b, 0x01009D08) &&
u32eq(mem + 0x837, 0x34A97801) &&
u32eq(mem + 0x891, 0xB1018420) &&
u32eq(mem + 0x89f, 0x018b20AE)) {
unp->_depAdr = 0x100;
if (unp->_info->_run == -1)
unp->_forced = 0x827;
unp->_strMem = mem[0x86e] | mem[0x872] << 8;
if (u16eq(mem + 0x8b7, 0xff5b)) {
mem[0x8b6] = 0x2c;
unp->_retAdr = READ_LE_UINT16(&mem[0x8ba]); // mem[0x8ba] | mem[0x8bb] << 8;
} else {
unp->_retAdr = READ_LE_UINT16(&mem[0x8b7]); // mem[0x8b7] | mem[0x8b8] << 8;
}
unp->_endAdr = 0xae;
unp->_idFlag = 1;
return;
}
}
/* PET||SLAN variant? */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x812, 0x20BD00A2) &&
u32eq(mem + 0x816, 0x033c9D08) &&
u32eq(mem + 0x863, 0xB103B420) &&
u32eq(mem + 0x86c, 0x03BB20AE)) {
unp->_depAdr = 0x33c;
if (unp->_info->_run == -1)
unp->_forced = 0x812;
unp->_strMem = mem[0x856] | mem[0x85a] << 8;
unp->_retAdr = READ_LE_UINT16(&mem[0x896]); // mem[0x896] | mem[0x897] << 8;
unp->_endAdr = 0xae;
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,166 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnTBCMultiComp(UnpStr *unp) {
byte *mem;
int p = 0, q = 0, strtmp;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
if (u32eqmasked(mem + 0x82c, 0xfffffffd, 0x9ACA0184) &&
u32eq(mem + 0x830, 0xA001004C) &&
u32eq(mem + 0x834, 0x84FD8400) &&
u32eq(mem + 0x8a2, 0x01494C01)) {
/*normal 2080*/
if (mem[0x84a] == 0x81) {
if (u32eq(mem + 0x820, 0x32BDE9A2)) {
unp->_forced = 0x820;
unp->_retAdr = READ_LE_UINT16(&mem[0x8b2]); // mem[0x8b2] | mem[0x8b3] << 8;
if (unp->_retAdr == 0x1e1) {
if (u32eq(mem + 0x916, 0x4CA87120)) {
p = *(unsigned short int *)(mem + 0x91a);
if (p == 0xa7ae) {
unp->_retAdr = p;
mem[0x8b2] = 0xae;
mem[0x8b3] = 0xa7;
} else {
mem[0x916] = 0x2c;
unp->_retAdr = p;
}
} else if ((mem[0x916] == 0x4C) || (mem[0x916] == 0x20)) {
unp->_retAdr = READ_LE_UINT16(&mem[0x917]); // mem[0x917] | mem[0x918] << 8;
} else if (mem[0x919] == 0x4c) {
unp->_retAdr = READ_LE_UINT16(&mem[0x91a]); // mem[0x91a] | mem[0x91b] << 8;
}
}
if ((unp->_retAdr == 0) && (mem[0x8b1] == 0)) {
unp->_retAdr = 0xa7ae;
mem[0x8b1] = 0x4c;
mem[0x8b2] = 0xae;
mem[0x8b3] = 0xa7;
}
p = 0x8eb;
}
}
/*firelord 2076*/
else if (mem[0x84a] == 0x7b) {
if (u32eq(mem + 0x81d, 0x32BDE9A2)) {
unp->_forced = 0x81d;
unp->_retAdr = READ_LE_UINT16(&mem[0x8ac]); // mem[0x8ac] | mem[0x8ad] << 8;
p = 0x8eb;
}
}
if (unp->_forced) {
unp->_depAdr = 0x100;
unp->_strMem = READ_LE_UINT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
q = p;
q += mem[p];
unp->_endAdr = 0;
for (; q > p; q -= 4) {
strtmp = READ_LE_UINT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
if (strtmp == 0)
strtmp = 0x10000;
if (strtmp > unp->_endAdr)
unp->_endAdr = strtmp;
}
unp->_idFlag = 1;
return;
}
}
}
/* TBC Multicompactor ? very similar but larger code */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x822, 0x9D083DBD) &&
u32eq(mem + 0x826, 0xD0CA0333) &&
u32eq(mem + 0x832, 0xF7D0CA00) &&
u32eq(mem + 0x836, 0xCA018678) &&
u32eq(mem + 0x946, 0xADC5AFA5)) {
if (unp->_info->_run == -1) {
for (p = 0x81e; p < 0x821; p++) {
if (mem[p] == 0xa2) {
unp->_forced = p;
break;
}
}
}
unp->_depAdr = 0x334;
unp->_retAdr = READ_LE_UINT16(&mem[0x92a]); // mem[0x92a] | mem[0x92b] << 8;
p = 0x94d;
unp->_strMem = READ_LE_UINT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
q = p;
q += mem[p];
unp->_endAdr = 0;
for (; q > p; q -= 4) {
strtmp = READ_LE_UINT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
if (strtmp == 0)
strtmp = 0x10000;
if (strtmp > unp->_endAdr)
unp->_endAdr = strtmp;
}
unp->_idFlag = 1;
return;
}
}
/*"AUTOMATIC BREAK SYSTEM" found in Manowar Cracks*/
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x835, 0x9D0845BD) &&
u32eq(mem + 0x839, 0xD0CA00ff) &&
u32eq(mem + 0x83e, 0xCA018678) &&
u32eq(mem + 0x8e1, 0xADC5AFA5)) {
if (unp->_info->_run == -1) {
for (p = 0x830; p < 0x834; p++) {
if (mem[p] == 0xa2) {
unp->_forced = p;
break;
}
}
}
unp->_depAdr = 0x100;
unp->_retAdr = READ_LE_UINT16(&mem[0x8c5]); // mem[0x8c5] | mem[0x8c6] << 8;
p = 0x8fe;
unp->_strMem = READ_LE_UINT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
q = p;
q += mem[p];
unp->_endAdr = 0;
for (; q > p; q -= 4) {
strtmp = READ_LE_UINT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
if (strtmp == 0)
strtmp = 0x10000;
if (strtmp > unp->_endAdr)
unp->_endAdr = strtmp;
}
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,78 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnTCScrunch(UnpStr *unp) {
byte *mem;
int q, p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x819, 0x018536A9) && mem[0x81d] == 0x4c) {
p = READ_LE_UINT16(&mem[0x81e]); // mem[0x81e] | mem[0x81f] << 8;
if (mem[p] == 0xa2 && mem[p + 2] == 0xbd &&
u32eq(mem + p + 0x05, 0xE801109D) &&
(u32eq(mem + p + 0x38, 0x01524CFB) ||
(u32eq(mem + p + 0x38, 0x8DE1A9FB) &&
u32eq(mem + p + 0x3c, 0x524C0328)))) {
unp->_depAdr = 0x334;
unp->_forced = 0x819;
unp->_endAdr = 0x2d;
}
} else if (u32eq(mem + 0x819, 0x018534A9) && mem[0x81d] == 0x4c) {
p = READ_LE_UINT16(&mem[0x81e]); // mem[0x81e] | mem[0x81f] << 8;
if (mem[p] == 0xa2 && mem[p + 2] == 0xbd &&
u32eq(mem + p + 0x05, 0xE801109D) &&
u32eq(mem + p + 0x38, 0x01304CFB)) {
unp->_depAdr = 0x334;
unp->_forced = 0x818;
if (mem[unp->_forced] != 0x78)
unp->_forced++;
unp->_endAdr = 0x2d;
unp->_retAdr = READ_LE_UINT16(&mem[p + 0xd9]); // mem[p + 0xd9] | mem[p + 0xda] << 8;
p += 0xc8;
q = p + 6;
for (; p < q; p += 3) {
if (mem[p] == 0x20 &&
u16gteq(mem + p + 1, 0xa000) &&
u16lteq(mem + p + 1, 0xbfff)) {
mem[p] = 0x2c;
}
}
}
}
if (unp->_depAdr) {
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,162 @@
/* 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/>.
*
*/
#include "common/endian.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/unp64.h"
#include "glk/scott/unp64/exo_util.h"
namespace Glk {
namespace Scott {
void scnXTC(UnpStr *unp) {
byte *mem;
int q = 0, p;
if (unp->_idFlag)
return;
mem = unp->_mem;
if (unp->_depAdr == 0) {
if (u16eq(mem + 0x80d, 0xE678) &&
u32eq(mem + 0x811, 0x1BCE0818) &&
u32eq(mem + 0x819, 0xC8000099) &&
u32eq(mem + 0x82c, 0x4CF7D0CA) &&
mem[0x85c] == 0x99) {
unp->_retAdr = READ_LE_UINT16(&mem[0x872]); // mem[0x872] | mem[0x873] << 8;
unp->_depAdr = 0x100;
unp->_forced = 0x80d; /* the ldy #$00 can be missing, skipped */
unp->_fEndAf = 0x121;
unp->_endAdC = 0xffff | EA_USE_Y;
unp->_strMem = READ_LE_UINT16(&mem[0x85d]); // mem[0x85d] | mem[0x85e] << 8;
unp->_idFlag = 1;
return;
}
}
/* XTC packer 1.0 & 2.2/2.4 */
if (unp->_depAdr == 0) {
for (p = 0x801; p < 0x80c; p += 0x0a) {
if (u16eq(mem + p + 0x02, 0xE678) &&
u32eq(mem + p + 0x07, (unsigned int)(0xce08 | ((p + 0x10) << 16))) &&
u32eq(mem + p + 0x0e, 0xC8000099) &&
u32eq(mem + p + 0x23, 0x4CF7D0CA)) {
/* has variable codebytes so addresses varies */
for (q = p + 0x37; q < p + 0x60; q += 4) {
if (mem[q] == 0xc9)
continue;
if (mem[q] == 0x99) {
unp->_depAdr = 0x100;
break;
}
break; /* unexpected byte, get out */
}
break;
}
}
if (unp->_depAdr) {
unp->_retAdr = READ_LE_UINT16(&mem[q + 0x16]); // mem[q + 0x16] | mem[q + 0x17] << 8;
if (u16noteq(mem + p, 0x00a0))
unp->_forced = p + 2; /* the ldy #$00 can be missing, skipped */
else
unp->_forced = p;
unp->_fEndAf = READ_LE_UINT16(&mem[q + 0x7]); // mem[q + 0x7] | mem[q + 0x8] << 8;
unp->_fEndAf--;
unp->_endAdC = 0xffff | EA_USE_Y;
unp->_strMem = READ_LE_UINT16(&mem[q + 1]); // mem[q + 1] | mem[q + 2] << 8;
if (u32eq(mem + q + 0x1f, 0xDDD00285)) {
} else if (u32eq(mem + q + 0x1f, 0xF620DFD0)) {
/* rockstar's 2.2+ & shade/light's 2.4 are all the same */
} else { /* actually found to be Visiomizer 6.2/Zagon */
unp->_depAdr = READ_LE_UINT16(&mem[p + 0x27]); // mem[p + 0x27] | mem[p + 0x28] << 8;
}
unp->_idFlag = 1;
return;
}
}
/* XTC 2.3 / 6codezipper */
if (unp->_depAdr == 0) {
if (u32eq(mem + 0x803, 0xB9018478) &&
u32eq(mem + 0x80b, 0xF7D0C8FF) &&
u32eq(mem + 0x81b, 0x00FC9D08) &&
u32eq(mem + 0x85b, 0xD0D0FFE4)) {
unp->_depAdr = READ_LE_UINT16(&mem[0x823]); // mem[0x823] | mem[0x824] << 8;
unp->_forced = 0x803;
unp->_retAdr = READ_LE_UINT16(&mem[0x865]); // mem[0x865] | mem[0x866] << 8;
unp->_strMem = READ_LE_UINT16(&mem[0x850]); // mem[0x850] | mem[0x851] << 8;
unp->_endAdC = 0xffff | EA_USE_Y;
unp->_fEndAf = 0x128;
unp->_idFlag = 1;
return;
}
}
/* XTC 2.3 / G*P, probably by Rockstar */
if (unp->_depAdr == 0) {
if ((u32eq(mem + 0x803, 0xB901e678) ||
u32eq(mem + 0x803, 0xB9018478)) &&
u32eq(mem + 0x80b, 0xF7D0C8FF) &&
u32eq(mem + 0x81b, 0x00F59D08) &&
u32eq(mem + 0x85b, 0xD0D0F8E4)) {
unp->_depAdr = READ_LE_UINT16(&mem[0x823]); // mem[0x823] | mem[0x824] << 8;
unp->_forced = 0x803;
unp->_retAdr = READ_LE_UINT16(&mem[0x865]); // mem[0x865] | mem[0x866] << 8;
unp->_strMem = READ_LE_UINT16(&mem[0x850]); // mem[0x850] | mem[0x851] << 8;
unp->_endAdC = 0xffff | EA_USE_Y;
unp->_fEndAf = 0x121;
unp->_idFlag = 1;
return;
}
}
/* XTC packer 2.x? found in G*P/NEI/Armageddon warez
just some different byte on copy loop, else is equal to 2.3
*/
if (unp->_depAdr == 0) {
for (p = 0x801; p < 0x80c; p += 0x0a) {
if (u32eqmasked(mem + p + 0x00, 0xffff0000, 0xE6780000) &&
u32eqmasked(mem + p + 0x05, 0xffff00ff, 0xB90800CE) &&
u32eq(mem + p + 0x0b, 0xC8000099) &&
u32eq(mem + p + 0x1e, 0x4CF7D0CA)) {
/* has variable codebytes so addresses varies */
for (q = p + 0x36; q < p + 0x60; q += 4) {
if (mem[q] == 0xc9)
continue;
if (mem[q] == 0x99) {
unp->_depAdr = 0x100;
break;
}
break; /* unexpected byte, get out */
}
break;
}
}
if (unp->_depAdr) {
unp->_retAdr = READ_LE_UINT16(&mem[q + 0x16]); // mem[q + 0x16] | mem[q + 0x17] << 8;
unp->_forced = p + 2;
unp->_fEndAf = READ_LE_UINT16(&mem[q + 0x7]); // mem[q + 0x7] | mem[q + 0x8] << 8;
unp->_fEndAf--;
unp->_endAdC = 0xffff | EA_USE_Y;
unp->_strMem = READ_LE_UINT16(&mem[q + 1]); // mem[q + 1] | mem[q + 2] << 8;
unp->_idFlag = 1;
return;
}
}
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,735 @@
/* 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/>.
*
*/
// This is a cut-down version of UNP64 with only the bare minimum
// needed to decompress a number of Scott Adams Commodore 64 games
// for the ScottFree interpreter.
/*
UNP64 - generic Commodore 64 prg unpacker
(C) 2008-2018 iAN CooG/HVSC Crew^C64Intros
original source and idea: testrun.c, taken from exo20b7
Follows original disclaimer
*/
/*
* Copyright (c) 2002 - 2023 Magnus Lind.
*
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*/
#include "glk/scott/globals.h"
#include "glk/scott/types.h"
#include "glk/scott/unp64/6502_emu.h"
#include "glk/scott/unp64/exo_util.h"
#include "glk/scott/unp64/unp64.h"
#include "common/util.h"
namespace Glk {
namespace Scott {
void reinitUnp(void) {
_G(_unp)._idFlag = 0;
_G(_unp)._forced = 0;
_G(_unp)._strMem = 0x800;
_G(_unp)._retAdr = 0x800;
_G(_unp)._depAdr = 0;
_G(_unp)._endAdr = 0x10000;
_G(_unp)._rtAFrc = 0;
_G(_unp)._wrMemF = 0;
_G(_unp)._lfMemF = 0;
_G(_unp)._exoFnd = 0;
_G(_unp)._ecaFlg = 0;
_G(_unp)._fEndBf = 0;
_G(_unp)._fEndAf = 0;
_G(_unp)._fStrAf = 0;
_G(_unp)._fStrBf = 0;
_G(_unp)._mon1st = 0;
}
int isBasicRun1(int pc) {
if (pc == 0xa7ae || pc == 0xa7ea || pc == 0xa7b1 || pc == 0xa474 || pc == 0xa533 || pc == 0xa871 || pc == 0xa888 || pc == 0xa8bc)
return 1;
else
return 0;
}
int isBasicRun2(int pc) {
if (isBasicRun1(pc) || ((pc >= 0xA57C) && (pc <= 0xA659)) || pc == 0xa660 || pc == 0xa68e)
return 1;
else
return 0;
}
int unp64(byte *compressed, size_t length, byte *destinationBuffer, size_t *finalLength, const char *switches) {
char settings[4][64];
int numSettings = 0;
if (switches != NULL) {
char string[100];
size_t string_length = strlen(switches);
if (string_length > 0 && string_length < 100) {
snprintf(string, sizeof string, "%s", switches);
char *setting = strtok(string, " ");
while (setting != NULL && numSettings < 4) {
snprintf(settings[numSettings], sizeof settings[numSettings], "%s", setting);
numSettings++;
setting = strtok(NULL, " ");
}
}
}
CpuCtx r[1];
LoadInfo info[1];
char name[260] = {0}, forcedname[260] = {0};
byte mem[65536] = {0}, oldmem[65536] = {0};
byte vector[0x20] = {0x31, 0xEA, 0x66, 0xFE, 0x47, 0xFE, 0x4A, 0xF3,
0x91, 0xF2, 0x0E, 0xF2, 0x50, 0xF2, 0x33, 0xF3,
0x57, 0xF1, 0xCA, 0xF1, 0xED, 0xF6, 0x3E, 0xF1,
0x2F, 0xF3, 0x66, 0xFE, 0xA5, 0xF4, 0xED, 0xF5};
byte stack[0x100] = {0x33, 0x38, 0x39, 0x31, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D,
0xEA, 0x00, 0x00, 0x82, 0x22, 0x0E, 0xBC, 0x81, 0x64, 0xB8,
0x0C, 0xBD, 0xBA, 0xB7, 0xBC, 0x03, 0x00, 0x46, 0xE1, 0xE9,
0xA7, 0xA7, 0x79, 0xA6, 0x9C, 0xE3};
int iterMax = ITERMAX;
int p;
memset(&_G(_unp), 0, sizeof(_G(_unp)));
reinitUnp();
_G(_unp)._fStack = 1;
_G(_unp)._mem = mem;
_G(_unp)._r = r;
_G(_unp)._name = name;
_G(_unp)._info = info;
p = 0;
if (numSettings != 0) {
if (settings[0][0] == '-' && _G(_parsePar) && settings[0][1] == 'f') {
strToInt(settings[p] + 2, (int *)&_G(_unp)._filler);
if (_G(_unp)._filler) {
memset(mem + (_G(_unp)._filler >> 16), _G(_unp)._filler & 0xff, 0x10000 - (_G(_unp)._filler >> 16));
}
p++;
}
}
looprecurse:
info->_basicTxtStart = 0x801;
loadData(compressed, length, mem, info);
/* no start address from load */
if (info->_run == -1) {
/* look for sys line */
info->_run = findSys(mem + info->_basicTxtStart, 0x9e);
}
scanners(&_G(_unp));
if (_G(_unp)._idFlag == 2)
return 0;
if ((_G(_unp)._recurs == 0) && (numSettings > 0)) {
while (p < numSettings) {
if (settings[p][0] == '-') {
switch (settings[p][1]) {
case '-':
p = numSettings;
break;
case 'e':
strToInt(settings[p] + 2, &_G(_unp)._forced);
_G(_unp)._forced &= 0xffff;
if (_G(_unp)._forced < 0x1)
_G(_unp)._forced = 0;
break;
case 'a':
_G(_unp)._strMem = 2;
_G(_unp)._endAdr = 0x10001;
_G(_unp)._fEndAf = 0;
_G(_unp)._fStrAf = 0;
_G(_unp)._strAdC = 0;
_G(_unp)._endAdC = 0;
_G(_unp)._monEnd = 0;
_G(_unp)._monStr = 0;
break;
case 'r':
strToInt(settings[p] + 2, &_G(_unp)._retAdr);
_G(_unp)._retAdr &= 0xffff;
break;
case 'R':
strToInt(settings[p] + 2, &_G(_unp)._retAdr);
_G(_unp)._retAdr &= 0xffff;
_G(_unp)._rtAFrc = 1;
break;
case 'd':
strToInt(settings[p] + 2, &_G(_unp)._depAdr);
_G(_unp)._depAdr &= 0xffff;
break;
case 't':
strToInt(settings[p] + 2, &_G(_unp)._endAdr);
_G(_unp)._endAdr &= 0xffff;
if (_G(_unp)._endAdr >= 0x100)
_G(_unp)._endAdr++;
break;
case 'u':
_G(_unp)._wrMemF = 1;
break;
case 'l':
_G(_unp)._lfMemF = info->_end;
break;
case 's':
_G(_unp)._fStack = 0;
break;
case 'x':
break;
case 'B':
//copyRoms[0][1] = 1;
break;
case 'K':
//copyRoms[1][1] = 1;
break;
case 'c':
_G(_unp)._recurs++;
break;
case 'm': // keep undocumented for now
strToInt(settings[p] + 2, &iterMax);
}
}
p++;
}
}
if (_G(_unp)._idOnly) {
if (_G(_unp)._depAdr == 0)
return 0;
}
if (_G(_unp)._wrMemF | _G(_unp)._lfMemF) {
memcpy(oldmem, mem, sizeof(oldmem));
}
if (_G(_unp)._forced) {
info->_run = _G(_unp)._forced;
}
if (info->_run == -1) {
return 0;
}
if (_G(_unp)._strMem > _G(_unp)._retAdr) {
_G(_unp)._strMem = _G(_unp)._retAdr;
}
mem[0] = 0x60;
r->_cycles = 0;
mem[1] = 0x37;
if (((_G(_unp)._forced >= 0xa000) && (_G(_unp)._forced < 0xc000)) || (_G(_unp)._forced >= 0xd000))
mem[1] = 0x38;
/* some packers rely on basic pointers already set */
mem[0x2b] = info->_basicTxtStart & 0xff;
mem[0x2c] = info->_basicTxtStart >> 8;
if (info->_basicVarStart == -1) {
mem[0x2d] = info->_end & 0xff;
mem[0x2e] = info->_end >> 8;
} else {
mem[0x2d] = info->_basicVarStart & 0xff;
mem[0x2e] = info->_basicVarStart >> 8;
}
mem[0x2f] = mem[0x2d];
mem[0x30] = mem[0x2e];
mem[0x31] = mem[0x2d];
mem[0x32] = mem[0x2e];
mem[0xae] = info->_end & 0xff;
mem[0xaf] = info->_end >> 8;
/* CCS unpacker requires $39/$3a (current basic line number) set */
mem[0x39] = mem[0x803];
mem[0x3a] = mem[0x804];
mem[0x52] = 0;
mem[0x53] = 3;
if (_G(_unp)._fStack) {
memcpy(mem + 0x100, stack,
sizeof(stack)); /* stack as found on clean start */
r->_sp = 0xf6; /* sys from immediate mode leaves $f6 in stackptr */
} else {
r->_sp = 0xff;
}
if (info->_start > (long int)(0x314 + sizeof(vector))) {
/* some packers use values in irq pointers to decrypt themselves */
memcpy(mem + 0x314, vector, sizeof(vector));
}
mem[0x200] = 0x8a;
r->_mem = mem;
r->_pc = info->_run;
r->_flags = 0x20;
r->_a = 0;
r->_y = 0;
if (info->_run > 0x351) /* temporary for XIP */ {
r->_x = 0;
}
_G(_iter) = 0;
while ((_G(_unp)._depAdr ? r->_pc != _G(_unp)._depAdr : r->_pc >= _G(_unp)._retAdr)) {
if ((((mem[1] & 0x7) >= 6) && (r->_pc >= 0xe000)) || ((r->_pc >= 0xa000) && (r->_pc <= 0xbfff) && ((mem[1] & 0x7) > 6))) {
/* some packer relies on regs set at return from CLRSCR */
if ((r->_pc == 0xe536) || (r->_pc == 0xe544) || (r->_pc == 0xff5b) || ((r->_pc == 0xffd2) && (r->_a == 0x93))) {
if (r->_pc != 0xffd2) {
r->_x = 0x01;
r->_y = 0x84;
if (r->_pc == 0xff5b)
r->_a = 0x97; /* actually depends on $d012 */
else
r->_a = 0xd8;
r->_flags &= ~(128 | 2);
r->_flags |= (r->_a == 0 ? 2 : 0) | (r->_a & 128);
}
memset(mem + 0x400, 0x20, 1000);
}
/* intros */
if ((r->_pc == 0xffe4) || (r->_pc == 0xf13e)) {
static int flipspe4 = -1;
static unsigned char fpressedchars[] = {0x20, 0, 0x4e, 0, 3, 0, 0x5f, 0, 0x11, 00, 0x0d, 0, 0x31, 0};
flipspe4++;
if (flipspe4 > ARRAYSIZE(fpressedchars))
flipspe4 = 0;
r->_a = fpressedchars[flipspe4];
r->_flags &= ~(128 | 2);
r->_flags |= (r->_a == 0 ? 2 : 0) | (r->_a & 128);
}
if (r->_pc == 0xfd15) {
r->_a = 0x31;
r->_x = 0x30;
r->_y = 0xff;
}
if (r->_pc == 0xfda3) {
mem[0x01] = 0xe7;
r->_a = 0xd7;
r->_x = 0xff;
}
if (r->_pc == 0xffbd) {
mem[0xB7] = r->_a;
mem[0xBB] = r->_x;
mem[0xBC] = r->_y;
}
if ((r->_pc == 0xffd5) || (r->_pc == 0xf4a2)) {
break;
}
if (isBasicRun1(r->_pc)) {
info->_run = findSys(mem + info->_basicTxtStart, 0x9e);
if (info->_run > 0) {
r->_sp = 0xf6;
r->_pc = info->_run;
} else {
mem[0] = 0x60;
r->_pc = 0; /* force a RTS instead of executing ROM code */
}
} else {
mem[0] = 0x60;
r->_pc = 0; /* force a RTS instead of executing ROM code */
}
}
if (nextInst(r) == 1)
return 0;
_G(_iter)++;
if (_G(_iter) == iterMax) {
return 0;
}
if (_G(_unp)._exoFnd && (_G(_unp)._endAdr == 0x10000) && (r->_pc >= 0x100) && (r->_pc <= 0x200) && (_G(_unp)._strMem != 2)) {
_G(_unp)._endAdr = r->_mem[0xfe] + (r->_mem[0xff] << 8);
if ((_G(_unp)._exoFnd & 0xff) == 0x30) { /* low byte of _endAdr, it's a lda $ff00,y */
_G(_unp)._endAdr = (_G(_unp)._exoFnd >> 8) + (r->_mem[0xff] << 8);
} else if ((_G(_unp)._exoFnd & 0xff) == 0x32) { /* add 1 */
_G(_unp)._endAdr = 1 + ((_G(_unp)._exoFnd >> 8) + (r->_mem[0xff] << 8));
}
if (_G(_unp)._endAdr == 0)
_G(_unp)._endAdr = 0x10001;
}
if (_G(_unp)._fEndBf && (_G(_unp)._endAdr == 0x10000) && (r->_pc == _G(_unp)._depAdr)) {
_G(_unp)._endAdr = r->_mem[_G(_unp)._fEndBf] | r->_mem[_G(_unp)._fEndBf + 1] << 8;
_G(_unp)._endAdr++;
if (_G(_unp)._endAdr == 0)
_G(_unp)._endAdr = 0x10001;
_G(_unp)._fEndBf = 0;
}
if (_G(_unp)._fStrBf && (_G(_unp)._strMem != 0x2) && (r->_pc == _G(_unp)._depAdr)) {
_G(_unp)._strMem = r->_mem[_G(_unp)._fStrBf] | r->_mem[_G(_unp)._fStrBf + 1] << 8;
_G(_unp)._fStrBf = 0;
}
if (_G(_unp)._debugP) {
for (p = 0; p < 0x20; p += 2) {
if (*(unsigned short int *)(mem + 0x314 + p) != *(unsigned short int *)(vector + p)) {
*(unsigned short int *)(vector + p) = *(unsigned short int *)(mem + 0x314 + p);
}
}
}
}
_G(_iter) = 0;
while (_G(_unp)._rtAFrc ? r->_pc != _G(_unp)._retAdr : r->_pc < _G(_unp)._retAdr) {
if (_G(_unp)._monEnd && r->_pc == _G(_unp)._depAdr) {
p = r->_mem[_G(_unp)._monEnd >> 16] | r->_mem[_G(_unp)._monEnd & 0xffff] << 8;
if (p > (_G(_unp)._endAdr & 0xffff)) {
_G(_unp)._endAdr = p;
}
}
if (_G(_unp)._monStr && r->_pc == _G(_unp)._depAdr) {
p = r->_mem[_G(_unp)._monStr >> 16] | r->_mem[_G(_unp)._monStr & 0xffff] << 8;
if (p > 0) {
if (_G(_unp)._mon1st == 0) {
_G(_unp)._strMem = p;
}
_G(_unp)._mon1st = (unsigned int)_G(_unp)._strMem;
_G(_unp)._strMem = (p < _G(_unp)._strMem ? p : _G(_unp)._strMem);
}
}
if (r->_pc >= 0xe000) {
if (((mem[1] & 0x7) >= 6) && ((mem[1] & 0x7) <= 7)) {
mem[0] = 0x60;
r->_pc = 0;
}
}
if (nextInst(r) == 1)
return 0;
if ((mem[r->_pc] == 0x40) && (_G(_unp)._rtiFrc == 1)) {
_G(_unp)._retAdr = r->_pc;
_G(_unp)._rtAFrc = 1;
if (_G(_unp)._retAdr < _G(_unp)._strMem)
_G(_unp)._strMem = 2;
break;
}
_G(_iter)++;
if (_G(_iter) == iterMax) {
return 0;
}
if ((r->_pc >= 0xa000) && (r->_pc <= 0xbfff) && ((mem[1] & 0x7) == 7)) {
if (isBasicRun2(r->_pc)) {
r->_pc = 0xa7ae;
break;
} else {
mem[0] = 0x60;
r->_pc = 0;
}
}
if (r->_pc >= 0xe000) {
if (((mem[1] & 0x7) >= 6) && ((mem[1] & 0x7) <= 7)) {
if (r->_pc == 0xffbd) {
mem[0xB7] = r->_a;
mem[0xBB] = r->_x;
mem[0xBC] = r->_y;
}
/* return into IRQ handler, better stop here */
if (((r->_pc >= 0xea31) && (r->_pc <= 0xeb76)) || (r->_pc == 0xffd5) || (r->_pc == 0xfce2)) {
break;
}
if (r->_pc == 0xfda3) {
mem[0x01] = 0xe7;
r->_a = 0xd7;
r->_x = 0xff;
}
mem[0] = 0x60;
r->_pc = 0;
}
}
}
if (_G(_unp)._fEndAf && _G(_unp)._monEnd) {
_G(_unp)._endAdC = (unsigned int)(mem[_G(_unp)._fEndAf] | mem[_G(_unp)._fEndAf + 1] << 8);
if ((int)_G(_unp)._endAdC > _G(_unp)._endAdr)
_G(_unp)._endAdr = (int)_G(_unp)._endAdC;
_G(_unp)._endAdC = 0;
_G(_unp)._fEndAf = 0;
}
if (_G(_unp)._fEndAf && (_G(_unp)._endAdr == 0x10000)) {
_G(_unp)._endAdr = r->_mem[_G(_unp)._fEndAf] | r->_mem[_G(_unp)._fEndAf + 1] << 8;
if (_G(_unp)._endAdr == 0)
_G(_unp)._endAdr = 0x10000;
else
_G(_unp)._endAdr++;
_G(_unp)._fEndAf = 0;
}
if (_G(_unp)._fStrAf /*&&(_G(_unp)._strMem==0x800)*/) {
_G(_unp)._strMem = r->_mem[_G(_unp)._fStrAf] | r->_mem[_G(_unp)._fStrAf + 1] << 8;
_G(_unp)._strMem++;
_G(_unp)._fStrAf = 0;
}
if (_G(_unp)._exoFnd && (_G(_unp)._strMem != 2)) {
_G(_unp)._strMem = r->_mem[0xfe] + (r->_mem[0xff] << 8);
if ((_G(_unp)._exoFnd & 0xff) == 0x30) {
_G(_unp)._strMem += r->_y;
} else if ((_G(_unp)._exoFnd & 0xff) == 0x32) {
_G(_unp)._strMem += r->_y + 1;
}
}
if (r->_pc == 0xfce2) {
if ((*(unsigned int *)(mem + 0x8004) == 0x38cdc2c3) && (mem[0x8008] == 0x30)) {
r->_pc = r->_mem[0x8000] + (r->_mem[0x8001] << 8);
}
} else if (r->_pc == 0xa7ae) {
info->_basicTxtStart = mem[0x2b] | mem[0x2c] << 8;
if (info->_basicTxtStart == 0x801) {
info->_run = findSys(mem + info->_basicTxtStart, 0x9e);
if (info->_run > 0)
r->_pc = info->_run;
}
}
if (_G(_unp)._wrMemF) {
_G(_unp)._wrMemF = 0;
for (p = 0x800; p < 0x10000; p += 4) {
if (*(unsigned int *)(oldmem + p) == *(unsigned int *)(mem + p)) {
*(unsigned int *)(mem + p) = 0;
_G(_unp)._wrMemF = 1;
}
}
/* clean also the $fd30 table copy in RAM */
if (memcmp(mem + 0xfd30, vector, sizeof(vector)) == 0) {
memset(mem + 0xfd30, 0, sizeof(vector));
}
}
if (_G(_unp)._lfMemF) {
for (p = 0xffff; p > 0x0800; p--) {
if (oldmem[--_G(_unp)._lfMemF] == mem[p])
mem[p] = 0x0;
else {
if (p >= 0xffff)
_G(_unp)._lfMemF = 0 | _G(_unp)._ecaFlg;
break;
}
}
}
if (*forcedname) {
Common::sprintf_s(name, sizeof name, "%s", forcedname);
} else {
size_t ln = strlen(name);
if (ln > 248) {/* dirty hack in case name is REALLY long */
name[248] = 0;
ln = 248;
}
Common::sprintf_s(name + ln, sizeof(name) - ln, ".%04x%s", r->_pc, ((_G(_unp)._wrMemF | _G(_unp)._lfMemF) ? ".clean" : ""));
}
/* endadr is set to a ZP location? then use it as a pointer
todo: use __fEndAf instead, it can be used for any location, not only ZP. */
if (_G(_unp)._endAdr && (_G(_unp)._endAdr < 0x100)) {
p = (mem[_G(_unp)._endAdr] | mem[_G(_unp)._endAdr + 1] << 8) & 0xffff;
_G(_unp)._endAdr = p;
}
if (_G(_unp)._ecaFlg && (_G(_unp)._strMem != 2)) /* checkme */ {
if (_G(_unp)._endAdr >= ((_G(_unp)._ecaFlg >> 16) & 0xffff)) {
/* most of the times transfers $2000 byte from $d000-efff to $e000-ffff but there are exceptions */
if (_G(_unp)._lfMemF)
memset(mem + ((_G(_unp)._ecaFlg >> 16) & 0xffff), 0, 0x1000);
_G(_unp)._endAdr += 0x1000;
}
}
if (_G(_unp)._endAdr <= 0)
_G(_unp)._endAdr = 0x10000;
if (_G(_unp)._endAdr > 0x10000)
_G(_unp)._endAdr = 0x10000;
if (_G(_unp)._endAdr < _G(_unp)._strMem)
_G(_unp)._endAdr = 0x10000;
if (_G(_unp)._endAdC & 0xffff) {
_G(_unp)._endAdr += (_G(_unp)._endAdC & 0xffff);
_G(_unp)._endAdr &= 0xffff;
}
if (_G(_unp)._endAdC & EA_USE_A) {
_G(_unp)._endAdr += r->_a;
_G(_unp)._endAdr &= 0xffff;
}
if (_G(_unp)._endAdC & EA_USE_X) {
_G(_unp)._endAdr += r->_x;
_G(_unp)._endAdr &= 0xffff;
}
if (_G(_unp)._endAdC & EA_USE_Y) {
_G(_unp)._endAdr += r->_y;
_G(_unp)._endAdr &= 0xffff;
}
if (_G(_unp)._strAdC & 0xffff) {
_G(_unp)._strMem += (_G(_unp)._strAdC & 0xffff);
_G(_unp)._strMem &= 0xffff;
/* only if ea_addff, no reg involved */
if (((_G(_unp)._strAdC & 0xffff0000) == EA_ADDFF) && ((_G(_unp)._strMem & 0xff) == 0)) {
_G(_unp)._strMem += 0x100;
_G(_unp)._strMem &= 0xffff;
}
}
if (_G(_unp)._strAdC & EA_USE_A) {
_G(_unp)._strMem += r->_a;
_G(_unp)._strMem &= 0xffff;
if (_G(_unp)._strAdC & EA_ADDFF) {
if ((_G(_unp)._strMem & 0xff) == 0xff)
_G(_unp)._strMem++;
if (r->_a == 0) {
_G(_unp)._strMem += 0x100;
_G(_unp)._strMem &= 0xffff;
}
}
}
if (_G(_unp)._strAdC & EA_USE_X) {
_G(_unp)._strMem += r->_x;
_G(_unp)._strMem &= 0xffff;
if (_G(_unp)._strAdC & EA_ADDFF) {
if ((_G(_unp)._strMem & 0xff) == 0xff)
_G(_unp)._strMem++;
if (r->_x == 0) {
_G(_unp)._strMem += 0x100;
_G(_unp)._strMem &= 0xffff;
}
}
}
if (_G(_unp)._strAdC & EA_USE_Y) {
_G(_unp)._strMem += r->_y;
_G(_unp)._strMem &= 0xffff;
if (_G(_unp)._strAdC & EA_ADDFF) {
if ((_G(_unp)._strMem & 0xff) == 0xff)
_G(_unp)._strMem++;
if (r->_y == 0) {
_G(_unp)._strMem += 0x100;
_G(_unp)._strMem &= 0xffff;
}
}
}
if (_G(_unp)._endAdr <= 0)
_G(_unp)._endAdr = 0x10000;
if (_G(_unp)._endAdr > 0x10000)
_G(_unp)._endAdr = 0x10000;
if (_G(_unp)._endAdr < _G(_unp)._strMem)
_G(_unp)._endAdr = 0x10000;
mem[_G(_unp)._strMem - 2] = _G(_unp)._strMem & 0xff;
mem[_G(_unp)._strMem - 1] = _G(_unp)._strMem >> 8;
memcpy(destinationBuffer, mem + (_G(_unp)._strMem - 2), (size_t)(_G(_unp)._endAdr - _G(_unp)._strMem + 2));
*finalLength = (size_t)(_G(_unp)._endAdr - _G(_unp)._strMem + 2);
if (_G(_unp)._recurs) {
if (++_G(_unp)._recurs > RECUMAX)
return 1;
reinitUnp();
goto looprecurse;
}
return 1;
}
} // End of namespace Scott
} // End of namespace Glk

View File

@@ -0,0 +1,78 @@
/* 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/>.
*
*/
#ifndef GLK_SCOTT_UNP64_H
#define GLK_SCOTT_UNP64_H
namespace Glk {
namespace Scott {
struct LoadInfo;
struct CpuCtx;
struct UnpStr {
int _idFlag; /* flag, 1=packer identified; 2=not a packer, stop scanning */
int _forced; /* forced entry point */
int _strMem; /* start of unpacked memory */
int _retAdr; /* return address after unpacking */
int _depAdr; /* unpacker entry point */
int _endAdr; /* end of unpacked memory */
int _rtAFrc; /* flag, return address must be exactly RetAdr, else anything >= RetAdr */
int _wrMemF; /* flag, clean unwritten memory */
int _lfMemF; /* flag, clean end memory leftovers */
int _exoFnd; /* flag, Exomizer detected */
int _fStack; /* flag, fill stack with 0 and SP=$ff, else as in C64 */
int _ecaFlg; /* ECA found, holds relocated areas high bytes */
int _fEndBf; /* End memory address pointer before unpacking, set when DepAdr is reached */
int _fEndAf; /* End memory address pointer after unpacking, set when RetAdr is reached */
int _fStrBf; /* Start memory address pointer before unpacking, set when DepAdr is reached */
int _fStrAf; /* Start memory address pointer after unpacking, set when RetAdr is reached */
int _idOnly; /* flag, just identify packer and exit */
int _debugP; /* flag, verbosely emit various infos */
int _rtiFrc; /* flag, RTI instruction forces return from unpacker */
int _recurs; /* recursion counter */
unsigned int _monEnd; /* End memory address pointers monitored during execution, updated every time DepAdr is reached */
unsigned int _monStr; /* Start memory address pointers monitored during execution, updated every time DepAdr is reached */
unsigned int _mon1st; /* flag for forcingly assign monitored str/end ptr the 1st time */
unsigned int _endAdC; /* add fixed values and/or registers AXY to End memory address */
unsigned int _strAdC; /* add fixed values and/or registers AXY to Start memory address */
unsigned int _filler; /* Memory filler byte*/
unsigned char *_mem; /* pointer to the memory array */
char *_name; /* name of the prg file */
LoadInfo *_info; /* pointer to the loaded prg info struct */
CpuCtx *_r; /* pointer to the registers struct */
};
typedef void (*Scnptr)(UnpStr *);
#define EA_USE_A 0x01000000
#define EA_USE_X 0x00100000
#define EA_USE_Y 0x00010000
#define EA_ADDFF 0x10000000
#define ITERMAX 0x02000000
#define RECUMAX 16
void scanners(UnpStr *);
} // End of namespace Scott
} // End of namespace Glk
#endif

View File

@@ -0,0 +1,35 @@
/* 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/>.
*
*/
#ifndef GLK_SCOTT_UNP64_INTERFACE_H
#define GLK_SCOTT_UNP64_INTERFACE_H
#include "glk/scott/types.h"
namespace Glk {
namespace Scott {
int unp64(uint8_t *compressed, size_t length, uint8_t *destinationBuffer, size_t *finalLength, const char *settings);
} // End of namespace Scott
} // End of namespace Glk
#endif