/*
dlditool - Dynamically Linked Disk Interface patch tool
Copyright (C) 2006 Michael Chisholm (Chishm)
Send all queries to chishm@hotmail.com
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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* v1.24d - 2010-06-14 - zeromus
* Modified for inclusion in desmume
* v1.24 - 2007-08-02 - SmileyDude
* Now using EXIT_SUCCESS and EXIT_FAILURE at the suggestion of MachinShin.
* Defined EXIT_NO_DLDI_SECTION for when there is no DLDI section in a file.
* Added cast to strcmp() call to appease the compiler.
* v1.23 - 2007-01-23 - Chishm
* Fixed bug when DLDI section doesn't exist
* addr_t is now a signed int
* v1.22 - 2007-01-12 - WinterMute
* add search paths for dldi files
* v1.21 - 2007-01-12 - Chishm
* Improved error messages
* v1.20 - 2007-01-11 - Chishm
* Changed offset calculation method
* v1.10 - 2007-01-07 - Chishm
* Removed assumptions about endianess of computer
* Word size shouldn't matter now either, except that an int type must be at least 32 bits long
* Added *.sc.nds and *.gba.nds file extensions
* Improved command line argument parsing
* v1.01 - 2006-12-30 - Chishm
* Minor bugfix parsing 3 arguments
* v1.00 - 2006-12-25 - Chishm
* Original release
*/
//#define VERSION "v1.24"
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cerrno>
#include <cstdlib>
#include <cstdarg>
#include "pstdint.h"
#ifndef _MSC_VER
# include <unistd.h>
# include <sys/param.h>
#else
#define MAXPATHLEN 1024
#endif
#include <sys/stat.h>
namespace DLDI
{
typedef int32_t addr_t;
typedef unsigned char data_t;
#define FEATURE_MEDIUM_CANREAD 0x00000001
#define FEATURE_MEDIUM_CANWRITE 0x00000002
#define FEATURE_SLOT_GBA 0x00000010
#define FEATURE_SLOT_NDS 0x00000020
#define MAGIC_TOKEN 0xBF8DA5ED
#define FIX_ALL 0x01
#define FIX_GLUE 0x02
#define FIX_GOT 0x04
#define FIX_BSS 0x08
#define DLDI_VERSION 1
#define EXIT_NO_DLDI_SECTION 2
enum DldiOffsets
{
DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm"
DO_magicToken = 0x00, // 0xBF8DA5ED
DO_magicShortString = 0x04, // " Chishm"
DO_version = 0x0C,
DO_driverSize = 0x0D,
DO_fixSections = 0x0E,
DO_allocatedSpace = 0x0F,
DO_friendlyName = 0x10,
DO_text_start = 0x40, // Data start
DO_data_end = 0x44, // Data end
DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing
DO_glue_end = 0x4C, // Interworking glue end
DO_got_start = 0x50, // GOT start -- Needs address fixing
DO_got_end = 0x54, // GOT end
DO_bss_start = 0x58, // bss start -- Needs setting to zero
DO_bss_end = 0x5C, // bss end
// IO_INTERFACE data
DO_ioType = 0x60,
DO_features = 0x64,
DO_startup = 0x68,
DO_isInserted = 0x6C,
DO_readSectors = 0x70,
DO_writeSectors = 0x74,
DO_clearStatus = 0x78,
DO_shutdown = 0x7C,
DO_code = 0x80
};
const data_t dldiMagicString[] = "\xED\xA5\x8D\xBF Chishm";
const char dldiFileExtension[] = ".dldi";
addr_t readAddr(data_t *mem, addr_t offset)
{
return static_cast<addr_t>(mem[offset + 0] | (mem[offset + 1] << 8) | (mem[offset + 2] << 16) | (mem[offset + 3] << 24));
}
void writeAddr(data_t *mem, addr_t offset, addr_t value)
{
mem[offset + 0] = static_cast<data_t>(value);
mem[offset + 1] = static_cast<data_t>(value >> 8);
mem[offset + 2] = static_cast<data_t>(value >> 16);
mem[offset + 3] = static_cast<data_t>(value >> 24);
}
int stringCaseInsensitiveCompare(const char *str1, const char *str2)
{
while (tolower(*str1) == tolower(*str2))
{
if (!*str1)
return 0;
++str1;
++str2;
}
return tolower(*str1) - tolower(*str2);
}
bool stringEndsWith(const char *str, const char *end)
{
if (strlen(str) < strlen(end))
return false;
const char *strEnd = &str[strlen (str) - strlen(end)];
return !stringCaseInsensitiveCompare(strEnd, end);
}
bool stringStartsWith(const char *str, const char *start)
{
return strstr(str, start) == str;
}
addr_t quickFind(const data_t *data, const data_t *search, size_t dataLen, size_t searchLen)
{
const int32_t *dataChunk = reinterpret_cast<const int32_t *>(data);
int searchChunk = reinterpret_cast<const int32_t *>(search)[0];
addr_t dataChunkEnd = static_cast<addr_t>(dataLen / sizeof(int32_t));
for (addr_t i = 0; i < dataChunkEnd; ++i)
{
if (dataChunk[i] == searchChunk)
{
if (i * sizeof(int32_t) + searchLen > dataLen)
return -1;
if (!memcmp(&data[i * sizeof(int32_t)], search, searchLen))
return i * sizeof(int32_t);
}
}
return -1;
}
FILE *openDLDIFile(const char *argv0, char *dldiFileName )
{
// add .dldi extension to filename
if (!stringEndsWith(dldiFileName, dldiFileExtension))
strcat(dldiFileName, dldiFileExtension);
printf("Trying \"%s\"\n", dldiFileName);
// try opening from current directory
FILE *dldiFile = fopen(dldiFileName, "rb");
if (dldiFile)
return dldiFile;
// check if the filename has a path component
// check both slash varieties, win32 understands both
// if we have a directory separator don't bother with search paths
if (strstr(dldiFileName, "\\"))
return nullptr;
if (strstr(dldiFileName ,"/"))
return nullptr;
// check for DLDIPATH in environment
char *dldiPATH = getenv("DLDIPATH");
char appPath[MAXPATHLEN];
if (dldiPATH)
{
strcpy(appPath, dldiPATH);
if (appPath[strlen(appPath)] != '\\' && appPath[strlen(appPath)] != '/')
strcat(appPath, "/");
strcat(appPath, dldiFileName);
printf("Trying \"%s\"\n", appPath);
dldiFile = fopen(appPath,"rb");
if (dldiFile)
return dldiFile;
}
char *lastSlash = nullptr;
char *ptr = const_cast<char *>(argv0);
while (*(ptr++))
if (*ptr == '\\' || * ptr == '/')
lastSlash = ptr;
char appName[MAXPATHLEN];
char appPathName[MAXPATHLEN];
if (lastSlash)
{
*(lastSlash++) = '\0';
strcpy(appPath, argv0);
strcpy(appName, lastSlash);
strcat(appPath, "/");
}
else
{
strcpy(appPath, "");
strcpy(appName, argv0);
}
// finally try in the application path
// if argv0 contains a directory separator we have a path component
if (!strstr(appPath,"\\") && !strstr(appPath,"/"))
{
// no path in argv0 so search system path
char *sysPATH = getenv("PATH");
char *thisPATH = sysPATH;
printf("Searching system path\n%s\n", sysPATH);
while (1)
{
char *nextPATH = strstr(thisPATH, ":" ); // find next PATH separator
if (nextPATH)
*(nextPATH++) = '\0'; // terminate string, point to next component
strcpy(appPath, thisPATH);
strcat(appPath, "/");
strcpy(appPathName, appPath);
strcat(appPathName, appName); // add application name
struct stat buf;
if (!stat(appPathName, &buf)) // if it exists we found the path
break;
thisPATH = nextPATH;
strcpy(appPath, "");// empty path
if (!thisPATH)
break;
}
}
strcat(appPath, "dldi/"); // add dldi folder
strcat(appPath, dldiFileName); // add dldi filename to path
printf("Trying \"%s\"\n", appPath);
return fopen(appPath, "rb"); // no more places to check, just return this handle
}
// Source File: mpcf.dldi
// Time: 6/14/2010 9:38 PM
// Orig. Offset: 0 / 0x00000000
// Length: 1876 / 0x00000754 (bytes)
data_t mpcf_dldi[] =
{
0xED, 0xA5, 0x8D, 0xBF, 0x20, 0x43, 0x68, 0x69, 0x73, 0x68, 0x6D, 0x00, 0x01, 0x0B, 0x0C, 0x00,
0x47, 0x42, 0x41, 0x20, 0x4D, 0x6F, 0x76, 0x69, 0x65, 0x20, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72,
0x20, 0x28, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x20, 0x46, 0x6C, 0x61, 0x73, 0x68, 0x29,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xBF, 0x54, 0x07, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF,
0x50, 0x07, 0x80, 0xBF, 0x50, 0x07, 0x80, 0xBF, 0x54, 0x07, 0x80, 0xBF, 0x70, 0x07, 0x80, 0xBF,
0x4D, 0x50, 0x43, 0x46, 0x13, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x80, 0xBF, 0x98, 0x01, 0x80, 0xBF,
0x78, 0x02, 0x80, 0xBF, 0xC8, 0x04, 0x80, 0xBF, 0xC8, 0x01, 0x80, 0xBF, 0x10, 0x07, 0x80, 0xBF,
0x0D, 0xC0, 0xA0, 0xE1, 0xF8, 0xDF, 0x2D, 0xE9, 0x04, 0xB0, 0x4C, 0xE2, 0x28, 0xD0, 0x4B, 0xE2,
0xF0, 0x6F, 0x9D, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x10, 0x40, 0x2D, 0xE9, 0x2C, 0x40, 0x9F, 0xE5,
0x00, 0x30, 0xD4, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x24, 0x20, 0x9F, 0xE5, 0x05, 0x00, 0x00, 0x1A,
0x00, 0x00, 0x52, 0xE3, 0x1C, 0x00, 0x9F, 0xE5, 0x0F, 0xE0, 0xA0, 0x11, 0x12, 0xFF, 0x2F, 0x11,
0x01, 0x30, 0xA0, 0xE3, 0x00, 0x30, 0xC4, 0xE5, 0x10, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1,
0x54, 0x07, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x48, 0x07, 0x80, 0xBF, 0x04, 0xE0, 0x2D, 0xE5,
0x40, 0x30, 0x9F, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x04, 0xD0, 0x4D, 0xE2, 0x38, 0x00, 0x9F, 0xE5,
0x38, 0x10, 0x9F, 0xE5, 0x0F, 0xE0, 0xA0, 0x11, 0x13, 0xFF, 0x2F, 0x11, 0x30, 0x00, 0x9F, 0xE5,
0x00, 0x30, 0x90, 0xE5, 0x00, 0x00, 0x53, 0xE3, 0x28, 0x30, 0x9F, 0xE5, 0x02, 0x00, 0x00, 0x0A,
0x00, 0x00, 0x53, 0xE3, 0x0F, 0xE0, 0xA0, 0x11, 0x13, 0xFF, 0x2F, 0x11, 0x04, 0xD0, 0x8D, 0xE2,
0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x48, 0x07, 0x80, 0xBF,
0x58, 0x07, 0x80, 0xBF, 0x4C, 0x07, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x09, 0x14, 0xA0, 0xE3,
0x06, 0x18, 0x81, 0xE2, 0xB0, 0x30, 0xD1, 0xE1, 0x03, 0x30, 0xE0, 0xE1, 0x03, 0x38, 0xA0, 0xE1,
0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0xB0, 0x30, 0xC1, 0xE1, 0xB0, 0x20, 0xD1, 0xE1,
0x04, 0xE0, 0x2D, 0xE5, 0xAA, 0xCC, 0xA0, 0xE3, 0x55, 0xEC, 0xE0, 0xE3, 0x03, 0x00, 0x52, 0xE1,
0xAA, 0xE0, 0x4E, 0xE2, 0x55, 0xC0, 0x8C, 0xE2, 0x00, 0x00, 0xA0, 0xE3, 0x03, 0x00, 0x00, 0x1A,
0xB0, 0xE0, 0xC1, 0xE1, 0xB0, 0x30, 0xD1, 0xE1, 0x0C, 0x00, 0x53, 0xE0, 0x01, 0x00, 0xA0, 0x13,
0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x26, 0x35, 0xA0, 0xE3, 0x03, 0x37, 0x83, 0xE2,
0x50, 0x20, 0xA0, 0xE3, 0xB0, 0x20, 0xC3, 0xE1, 0xB0, 0x00, 0xD3, 0xE1, 0x00, 0x08, 0xA0, 0xE1,
0x20, 0x08, 0xA0, 0xE1, 0xFF, 0x00, 0x00, 0xE2, 0x50, 0x00, 0x50, 0xE3, 0x00, 0x00, 0xA0, 0x13,
0x01, 0x00, 0xA0, 0x03, 0x1E, 0xFF, 0x2F, 0xE1, 0x09, 0x34, 0xA0, 0xE3, 0x0E, 0x38, 0x83, 0xE2,
0xB0, 0x20, 0xD3, 0xE1, 0x80, 0x00, 0x12, 0xE3, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0xA0, 0xE3,
0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x50, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3,
0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2,
0x80, 0x00, 0x12, 0xE3, 0x01, 0x00, 0x80, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A,
0x26, 0x15, 0xA0, 0xE3, 0x03, 0x17, 0x81, 0xE2, 0xB0, 0x30, 0xD1, 0xE1, 0x50, 0x30, 0x13, 0xE2,
0x01, 0x00, 0xA0, 0x13, 0x1E, 0xFF, 0x2F, 0x11, 0x26, 0x27, 0xA0, 0xE3, 0x96, 0x2C, 0x82, 0xE2,
0x03, 0x00, 0xA0, 0xE1, 0x80, 0x20, 0x82, 0xE2, 0x01, 0x00, 0x00, 0xEA, 0x02, 0x00, 0x50, 0xE1,
0x0A, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD1, 0xE1, 0x50, 0x30, 0x13, 0xE2, 0x01, 0x00, 0x80, 0xE2,
0xF9, 0xFF, 0xFF, 0x0A, 0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2,
0x03, 0x00, 0x50, 0xE1, 0x00, 0x00, 0xA0, 0xC3, 0x01, 0x00, 0xA0, 0xD3, 0x1E, 0xFF, 0x2F, 0xE1,
0x03, 0x00, 0xA0, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x4B, 0x2D, 0xE9, 0x09, 0x34, 0xA0, 0xE3,
0x0E, 0x38, 0x83, 0xE2, 0xB0, 0xC0, 0xD3, 0xE1, 0x80, 0x00, 0x1C, 0xE3, 0x10, 0xD0, 0x4D, 0xE2,
0x01, 0x90, 0xA0, 0xE1, 0x02, 0xE0, 0xA0, 0xE1, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0xC0, 0xA0, 0xE3,
0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x5C, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3,
0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2,
0x80, 0x00, 0x12, 0xE3, 0x01, 0xC0, 0x8C, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A,
0x26, 0xC5, 0xA0, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x30, 0x13, 0xE2,
0x26, 0x17, 0xA0, 0x03, 0x96, 0x1C, 0x81, 0x02, 0x03, 0x20, 0xA0, 0x01, 0x80, 0x10, 0x81, 0x02,
0x02, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, 0x67, 0x00, 0x00, 0x0A,
0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x00, 0x13, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF9, 0xFF, 0xFF, 0x0A,
0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1,
0x5E, 0x00, 0x00, 0xCA, 0xFF, 0x00, 0x59, 0xE3, 0x00, 0x30, 0xA0, 0x83, 0x0C, 0x30, 0x8D, 0x85,
0x5E, 0x00, 0x00, 0x9A, 0x00, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2,
0x09, 0x54, 0xA0, 0xE3, 0x04, 0x30, 0x8D, 0xE5, 0x0C, 0x30, 0x9D, 0xE5, 0x20, 0x4C, 0xA0, 0xE1,
0x0E, 0xB0, 0xA0, 0xE1, 0x05, 0x60, 0xA0, 0xE1, 0x20, 0x74, 0xA0, 0xE1, 0x05, 0x20, 0xA0, 0xE1,
0x20, 0x18, 0xA0, 0xE1, 0x05, 0xC0, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE1, 0x05, 0xE0, 0xA0, 0xE1,
0x01, 0x57, 0x85, 0xE2, 0xB0, 0x30, 0xC5, 0xE1, 0x04, 0x30, 0x9D, 0xE5, 0x0F, 0x40, 0x04, 0xE2,
0x06, 0x68, 0x86, 0xE2, 0xB0, 0x30, 0xC6, 0xE1, 0xFF, 0x70, 0x07, 0xE2, 0x02, 0x27, 0x82, 0xE2,
0xFF, 0x10, 0x01, 0xE2, 0x0A, 0x08, 0x80, 0xE2, 0xE0, 0x40, 0x84, 0xE3, 0x03, 0xC7, 0x8C, 0xE2,
0x0E, 0xE8, 0x8E, 0xE2, 0x20, 0x30, 0xA0, 0xE3, 0xB0, 0x70, 0xC2, 0xE1, 0xB0, 0x10, 0xC0, 0xE1,
0xB0, 0x40, 0xCC, 0xE1, 0xB0, 0x30, 0xCE, 0xE1, 0x0B, 0x80, 0xA0, 0xE1, 0x01, 0x90, 0x59, 0xE2,
0x3E, 0x00, 0x00, 0x3A, 0x26, 0x25, 0xA0, 0xE3, 0x03, 0x27, 0x82, 0xE2, 0xB0, 0x30, 0xD2, 0xE1,
0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3,
0x26, 0x17, 0xA0, 0x13, 0x96, 0x1C, 0x81, 0x12, 0x02, 0x00, 0xA0, 0x11, 0x80, 0x10, 0x81, 0x12,
0x00, 0x20, 0xA0, 0x13, 0x02, 0x00, 0x00, 0x1A, 0x0D, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1,
0x26, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD0, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1,
0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF6, 0xFF, 0xFF, 0x1A,
0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1,
0x1A, 0x00, 0x00, 0xCA, 0x01, 0x00, 0x18, 0xE3, 0x0B, 0x10, 0xA0, 0x01, 0xFF, 0x20, 0xA0, 0x03,
0x09, 0x04, 0xA0, 0x03, 0x0E, 0x00, 0x00, 0x0A, 0x08, 0x10, 0xA0, 0xE1, 0xFF, 0x00, 0xA0, 0xE3,
0x09, 0xC4, 0xA0, 0xE3, 0xB0, 0x30, 0xDC, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1,
0x01, 0x00, 0x40, 0xE2, 0x43, 0x24, 0xA0, 0xE1, 0x01, 0x00, 0x70, 0xE3, 0x01, 0x20, 0xC1, 0xE5,
0x00, 0x30, 0xC1, 0xE5, 0x02, 0x10, 0x81, 0xE2, 0xF5, 0xFF, 0xFF, 0x1A, 0x02, 0x8C, 0x88, 0xE2,
0xCD, 0xFF, 0xFF, 0xEA, 0x01, 0x20, 0x42, 0xE2, 0xB0, 0x30, 0xD0, 0xE1, 0x01, 0x00, 0x72, 0xE3,
0xB2, 0x30, 0xC1, 0xE0, 0xFA, 0xFF, 0xFF, 0x1A, 0x02, 0xBC, 0x8B, 0xE2, 0xC6, 0xFF, 0xFF, 0xEA,
0x00, 0x00, 0xA0, 0xE3, 0x10, 0xD0, 0x8D, 0xE2, 0xF0, 0x4B, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1,
0x09, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0x0C, 0x30, 0x8D, 0xE5, 0x9C, 0xFF, 0xFF, 0xEA,
0x01, 0x00, 0xA0, 0xE3, 0xF6, 0xFF, 0xFF, 0xEA, 0xF0, 0x4B, 0x2D, 0xE9, 0x09, 0x34, 0xA0, 0xE3,
0x0E, 0x38, 0x83, 0xE2, 0xB0, 0xC0, 0xD3, 0xE1, 0x80, 0x00, 0x1C, 0xE3, 0x10, 0xD0, 0x4D, 0xE2,
0x01, 0x90, 0xA0, 0xE1, 0x02, 0xE0, 0xA0, 0xE1, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0xC0, 0xA0, 0xE3,
0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x5C, 0xE1, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x34, 0xA0, 0xE3,
0x0E, 0x38, 0x83, 0xE2, 0xB0, 0x20, 0xD3, 0xE1, 0x26, 0x17, 0xA0, 0xE3, 0x96, 0x1C, 0x81, 0xE2,
0x80, 0x00, 0x12, 0xE3, 0x01, 0xC0, 0x8C, 0xE2, 0x80, 0x10, 0x81, 0xE2, 0xF4, 0xFF, 0xFF, 0x1A,
0x26, 0xC5, 0xA0, 0xE3, 0x03, 0xC7, 0x8C, 0xE2, 0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x30, 0x13, 0xE2,
0x26, 0x17, 0xA0, 0x03, 0x96, 0x1C, 0x81, 0x02, 0x03, 0x20, 0xA0, 0x01, 0x80, 0x10, 0x81, 0x02,
0x02, 0x00, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1, 0x65, 0x00, 0x00, 0x0A,
0xB0, 0x30, 0xDC, 0xE1, 0x50, 0x00, 0x13, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF9, 0xFF, 0xFF, 0x0A,
0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1,
0x5C, 0x00, 0x00, 0xCA, 0xFF, 0x00, 0x59, 0xE3, 0x00, 0x30, 0xA0, 0x83, 0x0C, 0x30, 0x8D, 0x85,
0x5C, 0x00, 0x00, 0x9A, 0x00, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2,
0x09, 0x54, 0xA0, 0xE3, 0x04, 0x30, 0x8D, 0xE5, 0x0C, 0x30, 0x9D, 0xE5, 0x20, 0x4C, 0xA0, 0xE1,
0x0E, 0xB0, 0xA0, 0xE1, 0x05, 0x60, 0xA0, 0xE1, 0x20, 0x74, 0xA0, 0xE1, 0x05, 0x20, 0xA0, 0xE1,
0x20, 0x18, 0xA0, 0xE1, 0x05, 0xC0, 0xA0, 0xE1, 0x05, 0x00, 0xA0, 0xE1, 0x05, 0xE0, 0xA0, 0xE1,
0x01, 0x57, 0x85, 0xE2, 0xB0, 0x30, 0xC5, 0xE1, 0x04, 0x30, 0x9D, 0xE5, 0x0F, 0x40, 0x04, 0xE2,
0x06, 0x68, 0x86, 0xE2, 0xB0, 0x30, 0xC6, 0xE1, 0xFF, 0x70, 0x07, 0xE2, 0x02, 0x27, 0x82, 0xE2,
0xFF, 0x10, 0x01, 0xE2, 0x0A, 0x08, 0x80, 0xE2, 0xE0, 0x40, 0x84, 0xE3, 0x03, 0xC7, 0x8C, 0xE2,
0x0E, 0xE8, 0x8E, 0xE2, 0x30, 0x30, 0xA0, 0xE3, 0xB0, 0x70, 0xC2, 0xE1, 0xB0, 0x10, 0xC0, 0xE1,
0xB0, 0x40, 0xCC, 0xE1, 0xB0, 0x30, 0xCE, 0xE1, 0x0B, 0x80, 0xA0, 0xE1, 0x01, 0x90, 0x59, 0xE2,
0x3C, 0x00, 0x00, 0x3A, 0x26, 0x25, 0xA0, 0xE3, 0x03, 0x27, 0x82, 0xE2, 0xB0, 0x30, 0xD2, 0xE1,
0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1, 0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3,
0x26, 0x17, 0xA0, 0x13, 0x96, 0x1C, 0x81, 0x12, 0x02, 0x00, 0xA0, 0x11, 0x80, 0x10, 0x81, 0x12,
0x00, 0x20, 0xA0, 0x13, 0x02, 0x00, 0x00, 0x1A, 0x0D, 0x00, 0x00, 0xEA, 0x01, 0x00, 0x52, 0xE1,
0x24, 0x00, 0x00, 0x0A, 0xB0, 0x30, 0xD0, 0xE1, 0x03, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1,
0xFF, 0x30, 0x03, 0xE2, 0x58, 0x00, 0x53, 0xE3, 0x01, 0x20, 0x82, 0xE2, 0xF6, 0xFF, 0xFF, 0x1A,
0x26, 0x37, 0xA0, 0xE3, 0x96, 0x3C, 0x83, 0xE2, 0x7F, 0x30, 0x83, 0xE2, 0x03, 0x00, 0x52, 0xE1,
0x18, 0x00, 0x00, 0xCA, 0x01, 0x00, 0x18, 0xE3, 0x0B, 0x10, 0xA0, 0x01, 0xFF, 0x20, 0xA0, 0x03,
0x09, 0x04, 0xA0, 0x03, 0x0C, 0x00, 0x00, 0x0A, 0x08, 0x10, 0xA0, 0xE1, 0xFF, 0x00, 0xA0, 0xE3,
0x09, 0xC4, 0xA0, 0xE3, 0x00, 0x30, 0xD1, 0xE5, 0x01, 0x20, 0xD1, 0xE5, 0x01, 0x00, 0x40, 0xE2,
0x02, 0x34, 0x83, 0xE1, 0x01, 0x00, 0x70, 0xE3, 0xB0, 0x30, 0xCC, 0xE1, 0x02, 0x10, 0x81, 0xE2,
0xF7, 0xFF, 0xFF, 0x1A, 0x02, 0x8C, 0x88, 0xE2, 0xCF, 0xFF, 0xFF, 0xEA, 0x01, 0x20, 0x42, 0xE2,
0xB2, 0x30, 0xD1, 0xE0, 0x01, 0x00, 0x72, 0xE3, 0xB0, 0x30, 0xC0, 0xE1, 0xFA, 0xFF, 0xFF, 0x1A,
0x02, 0xBC, 0x8B, 0xE2, 0xC8, 0xFF, 0xFF, 0xEA, 0x00, 0x00, 0xA0, 0xE3, 0x10, 0xD0, 0x8D, 0xE2,
0xF0, 0x4B, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x09, 0x38, 0xA0, 0xE1, 0x23, 0x38, 0xA0, 0xE1,
0x0C, 0x30, 0x8D, 0xE5, 0x9E, 0xFF, 0xFF, 0xEA, 0x01, 0x00, 0xA0, 0xE3, 0xF6, 0xFF, 0xFF, 0xEA,
0x04, 0xE0, 0x2D, 0xE5, 0x04, 0xD0, 0x4D, 0xE2, 0xAA, 0xFE, 0xFF, 0xEB, 0x04, 0xD0, 0x8D, 0xE2,
0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x0D, 0xC0, 0xA0, 0xE1, 0xF8, 0xDF, 0x2D, 0xE9,
0x04, 0xB0, 0x4C, 0xE2, 0x28, 0xD0, 0x4B, 0xE2, 0xF0, 0x6F, 0x9D, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1,
0xDC, 0x00, 0x80, 0xBF, 0x98, 0x00, 0x80, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}; //unsigned char mpcf_dldi[1876]
bool tryPatch(void *data, size_t size)
{
// Find the DSDI reserved space in the file
addr_t patchOffset = quickFind(static_cast<data_t *>(data), dldiMagicString, size, sizeof(dldiMagicString) / sizeof(char));
// no DLDI section
if (patchOffset < 0)
return false;
data_t *pDH = mpcf_dldi;
data_t *pAH = static_cast<data_t *>(data) + patchOffset;
if (pDH[DO_driverSize] > pAH[DO_allocatedSpace])
{
printf("Not enough space for patch. Available %d bytes, need %d bytes\n", 1 << pAH[DO_allocatedSpace], 1 << pDH[DO_driverSize]);
return false;
}
if (memcmp(&pAH[DO_friendlyName], "Default (No interface)", 22))
{
printf("Would have been a candidate for auto-patch DLDI, but there was already a patch installed.");
return false;
}
//----should be able to patch OK-----
addr_t memOffset; // Offset of DLDI after the file is loaded into memory
addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly
addr_t ddmemOffset; // Original offset used in the DLDI file
addr_t ddmemStart; // Start of range that offsets can be in the DLDI file
addr_t ddmemEnd; // End of range that offsets can be in the DLDI file
addr_t ddmemSize; // Size of range that offsets can be in the DLDI file
addr_t addrIter;
memOffset = readAddr(pAH, DO_text_start);
if (!memOffset)
memOffset = readAddr(pAH, DO_startup) - DO_code;
ddmemOffset = readAddr(pDH, DO_text_start);
relocationOffset = memOffset - ddmemOffset;
printf("AUTO-PATCHING DLDI to MPCF! Lucky you!\n\n");
printf("Old driver: %s\n", &pAH[DO_friendlyName]);
printf("New driver: %s\n", &pDH[DO_friendlyName]);
printf("\n");
printf("Position in file: 0x%08X\n", patchOffset);
printf("Position in memory: 0x%08X\n", memOffset);
printf("Patch base address: 0x%08X\n", ddmemOffset);
printf("Relocation offset: 0x%08X\n", relocationOffset);
printf("\n");
ddmemStart = readAddr(pDH, DO_text_start);
ddmemSize = 1 << pDH[DO_driverSize];
ddmemEnd = ddmemStart + ddmemSize;
// Remember how much space is actually reserved
pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace];
// Copy the DLDI patch into the application
memcpy(pAH, pDH, sizeof(mpcf_dldi));
// Fix the section pointers in the header
writeAddr(pAH, DO_text_start, readAddr(pAH, DO_text_start) + relocationOffset);
writeAddr(pAH, DO_data_end, readAddr(pAH, DO_data_end) + relocationOffset);
writeAddr(pAH, DO_glue_start, readAddr(pAH, DO_glue_start) + relocationOffset);
writeAddr(pAH, DO_glue_end, readAddr(pAH, DO_glue_end) + relocationOffset);
writeAddr(pAH, DO_got_start, readAddr(pAH, DO_got_start) + relocationOffset);
writeAddr(pAH, DO_got_end, readAddr(pAH, DO_got_end) + relocationOffset);
writeAddr(pAH, DO_bss_start, readAddr(pAH, DO_bss_start) + relocationOffset);
writeAddr(pAH, DO_bss_end, readAddr(pAH, DO_bss_end) + relocationOffset);
// Fix the function pointers in the header
writeAddr(pAH, DO_startup, readAddr(pAH, DO_startup) + relocationOffset);
writeAddr(pAH, DO_isInserted, readAddr(pAH, DO_isInserted) + relocationOffset);
writeAddr(pAH, DO_readSectors, readAddr(pAH, DO_readSectors) + relocationOffset);
writeAddr(pAH, DO_writeSectors, readAddr(pAH, DO_writeSectors) + relocationOffset);
writeAddr(pAH, DO_clearStatus, readAddr(pAH, DO_clearStatus) + relocationOffset);
writeAddr(pAH, DO_shutdown, readAddr(pAH, DO_shutdown) + relocationOffset);
if (pDH[DO_fixSections] & FIX_ALL)
// Search through and fix pointers within the data section of the file
for (addrIter = readAddr(pDH, DO_text_start) - ddmemStart; addrIter < readAddr(pDH, DO_data_end) - ddmemStart; ++addrIter)
if (ddmemStart <= readAddr(pAH, addrIter) && readAddr(pAH, addrIter) < ddmemEnd)
writeAddr(pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset);
if (pDH[DO_fixSections] & FIX_GLUE)
// Search through and fix pointers within the glue section of the file
for (addrIter = readAddr(pDH, DO_glue_start) - ddmemStart; addrIter < readAddr(pDH, DO_glue_end) - ddmemStart; ++addrIter)
if (ddmemStart <= readAddr(pAH, addrIter) && readAddr(pAH, addrIter) < ddmemEnd)
writeAddr(pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset);
if (pDH[DO_fixSections] & FIX_GOT)
// Search through and fix pointers within the Global Offset Table section of the file
for (addrIter = readAddr(pDH, DO_got_start) - ddmemStart; addrIter < readAddr(pDH, DO_got_end) - ddmemStart; ++addrIter)
if (ddmemStart <= readAddr(pAH, addrIter) && readAddr(pAH, addrIter) < ddmemEnd)
writeAddr(pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset);
if (pDH[DO_fixSections] & FIX_BSS)
// Initialise the BSS to 0
memset(&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start));
return true;
}
} //namespace DLDI