git subrepo clone (merge) https://github.com/HarbourMasters/otrgui.git OTRGui
subrepo: subdir: "OTRGui" merged: "a6066a251" upstream: origin: "https://github.com/HarbourMasters/otrgui.git" branch: "master" commit: "a6066a251" git-subrepo: version: "0.4.1" origin: "???" commit: "???"
This commit is contained in:
212
OTRGui/src/impl/baserom_extractor/baserom_extractor.cpp
Normal file
212
OTRGui/src/impl/baserom_extractor/baserom_extractor.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
#include "baserom_extractor.h"
|
||||
#include "utils/mutils.h"
|
||||
#include "yaz0/yaz0.h"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#define DMA_ENTRY_SIZE 16
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#define __bswap_32 _byteswap_ulong
|
||||
#define bswap_32 _byteswap_ulong
|
||||
#endif
|
||||
|
||||
//Rom DMA table start
|
||||
|
||||
#define OOT_OFF_NTSC_10_RC 0x7430
|
||||
#define OOT_OFF_NTSC_10 0x7430
|
||||
#define OOT_OFF_NTSC_11 0x7430
|
||||
#define OOT_OFF_PAL_10 0x7950
|
||||
#define OOT_OFF_NTSC_12 0x7960
|
||||
#define OOT_OFF_PAL_11 0x7950
|
||||
#define OOT_OFF_JP_GC 0x7170
|
||||
#define OOT_OFF_JP_MQ 0x7170
|
||||
#define OOT_OFF_US_GC 0x7170
|
||||
#define OOT_OFF_US_MQ 0x7170
|
||||
#define OOT_OFF_PAL_GC_DBG1 0x12F70
|
||||
#define OOT_OFF_PAL_MQ_DBG 0x12F70
|
||||
#define OOT_OFF_PAL_GC_DBG2 0x12F70
|
||||
#define OOT_OFF_PAL_GC 0x7170
|
||||
#define OOT_OFF_PAL_MQ 0x7170
|
||||
#define OOT_OFF_JP_GC_CE 007170
|
||||
#define OOT_OFF_CN_IQUE 0xB7A0
|
||||
#define OOT_OFF_TW_IQUE 0xB240
|
||||
|
||||
#define MM_OFF_US_10 0x1A500
|
||||
#define MM_OFF_JP_10 0x1C110
|
||||
#define MM_OFF_JP_11 0x1C050
|
||||
#define MM_OFF_DBG 0x24F60
|
||||
|
||||
RomVersion GetVersion(FILE* rom) {
|
||||
RomVersion version;
|
||||
|
||||
fseek(rom, 0x10, SEEK_SET);
|
||||
|
||||
if (fread(&version.crc, sizeof(uint32_t), 1, rom) != 1) {
|
||||
version.error = "Could not read rom CRC";
|
||||
return version;
|
||||
}
|
||||
|
||||
version.crc = __bswap_32(version.crc);
|
||||
switch (version.crc) {
|
||||
case OOT_NTSC_10:
|
||||
version.version = "N64 NTSC 1.0";
|
||||
version.listPath = "ntsc_oot.txt";
|
||||
version.offset = OOT_OFF_NTSC_10;
|
||||
break;
|
||||
case OOT_NTSC_11:
|
||||
version.version = "N64 NTSC 1.1";
|
||||
version.listPath = "ntsc_oot.txt";
|
||||
version.offset = OOT_OFF_NTSC_11;
|
||||
break;
|
||||
case OOT_NTSC_12:
|
||||
version.version = "N64 NTSC 1.2";
|
||||
version.listPath = "ntsc_oot.txt";
|
||||
version.offset = OOT_OFF_NTSC_12;
|
||||
break;
|
||||
case OOT_PAL_10:
|
||||
version.version = "N64 PAL 1.0";
|
||||
version.listPath = "pal_oot.txt";
|
||||
version.offset = OOT_OFF_PAL_10;
|
||||
break;
|
||||
case OOT_PAL_11:
|
||||
version.version = "N64 PAL 1.1";
|
||||
version.listPath = "pal_oot.txt";
|
||||
version.offset = OOT_OFF_PAL_11;
|
||||
break;
|
||||
case OOT_NTSC_JP_GC:
|
||||
version.version = "JP GameCube (MQ Disk)";
|
||||
version.listPath = "gamecube_mq.txt";
|
||||
version.offset = OOT_OFF_JP_GC;
|
||||
break;
|
||||
case OOT_NTSC_JP_GC_CE:
|
||||
version.version = "GameCube (Collectors Edition Disk)";
|
||||
version.listPath = "gamecube_mq.txt";
|
||||
version.offset = OOT_OFF_JP_GC_CE;
|
||||
break;
|
||||
case OOT_NTSC_JP_MQ:
|
||||
version.version = "JP Master Quest";
|
||||
version.listPath = "gamecube_mq.txt";
|
||||
version.offset = OOT_OFF_JP_MQ;
|
||||
break;
|
||||
case OOT_NTSC_US_MQ:
|
||||
version.version = "NTSC Master Quest";
|
||||
version.listPath = "gamecube_mq.txt";
|
||||
version.offset = OOT_OFF_JP_MQ;
|
||||
break;
|
||||
case OOT_NTSC_US_GC:
|
||||
version.version = "NTSC GameCube";
|
||||
version.listPath = "gamecube_mq.txt";
|
||||
version.offset = OOT_OFF_US_MQ;
|
||||
break;
|
||||
case OOT_PAL_GC:
|
||||
version.version = "PAL GameCube";
|
||||
version.listPath = "gamecube_mq.txt";
|
||||
version.offset = OOT_OFF_PAL_GC;
|
||||
break;
|
||||
case OOT_PAL_MQ:
|
||||
version.version = "PAL Master Quest";
|
||||
version.listPath = "pal_mq.txt";
|
||||
version.offset = OOT_OFF_PAL_MQ;
|
||||
break;
|
||||
case OOT_PAL_GC_DBG1:
|
||||
version.version = "GameCube Debug 1.0";
|
||||
version.listPath = "dbg.txt";
|
||||
version.offset = OOT_OFF_PAL_GC_DBG1;
|
||||
break;
|
||||
case OOT_PAL_GC_DBG2:
|
||||
version.version = "GameCube Debug 2.0";
|
||||
version.listPath = "dbg.txt";
|
||||
version.offset = OOT_OFF_PAL_GC_DBG2;
|
||||
break;
|
||||
case OOT_PAL_GC_MQ_DBG:
|
||||
version.version = "GameCube MQ-Debug";
|
||||
version.listPath = "dbg.txt";
|
||||
version.offset = OOT_OFF_PAL_MQ_DBG;
|
||||
break;
|
||||
case OOT_IQUE_CN:
|
||||
version.version = "OoT IQue";
|
||||
version.listPath = "ique.txt";
|
||||
version.offset = OOT_OFF_CN_IQUE;
|
||||
break;
|
||||
case OOT_IQUE_TW:
|
||||
version.version = "TW IQue";
|
||||
version.listPath = "ique.txt";
|
||||
version.offset = OOT_OFF_TW_IQUE;
|
||||
break;
|
||||
default:
|
||||
version.error = MoonUtils::format("Unknown CRC %x given: ", version.crc);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
std::string read(const std::string& file) {
|
||||
if (std::ifstream in(file, std::ios::in | std::ios::binary); in)
|
||||
return { std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>() };
|
||||
return "None";
|
||||
}
|
||||
|
||||
int to_int(char* buffer) {
|
||||
int a;
|
||||
memcpy(&a, buffer, sizeof(int));
|
||||
return a;
|
||||
}
|
||||
|
||||
WriteResult ExtractBaserom(const char* romPath) {
|
||||
FILE* rom = fopen(romPath, "rb");
|
||||
RomVersion version = GetVersion(rom);
|
||||
WriteResult result;
|
||||
|
||||
if (rom == nullptr) {
|
||||
result.error = "Could not open baserom.z64";
|
||||
return result;
|
||||
}
|
||||
|
||||
fseek(rom, 0, SEEK_END);
|
||||
const long romSize = ftell(rom);
|
||||
char* romData = new char[romSize];
|
||||
rewind(rom);
|
||||
fread(romData, sizeof(char), romSize, rom);
|
||||
|
||||
MoonUtils::mkdir("tmp/baserom/");
|
||||
|
||||
const std::vector<std::string> lines = MoonUtils::split(read(MoonUtils::join("assets/extractor/filelists", version.listPath)), '\n');
|
||||
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
FILE* outFile = fopen(MoonUtils::join("tmp/baserom", lines[i]).c_str(), "wb");
|
||||
const int romOffset = version.offset + (DMA_ENTRY_SIZE * i);
|
||||
|
||||
const int virtStart = bswap_32(to_int(romData + romOffset));
|
||||
const int virtEnd = bswap_32(to_int(romData + romOffset + 4));
|
||||
const int physStart = bswap_32(to_int(romData + romOffset + 8));
|
||||
const int physEnd = bswap_32(to_int(romData + romOffset + 12));
|
||||
|
||||
printf("File: %s vStart: 0x%08X vEnd: 0x%08X pStart: 0x%08X pEnd: 0x%08X\n", lines[i].c_str(), virtStart, virtEnd, physStart, physEnd);
|
||||
|
||||
const bool compressed = physEnd != 0;
|
||||
int size = compressed ? physEnd - physStart : virtEnd - virtStart;
|
||||
|
||||
auto outData = new uint8_t[size];
|
||||
memcpy(outData, romData + physStart, size);
|
||||
|
||||
if (compressed) {
|
||||
std::vector<uint8_t> compressedData = yaz0_encode(outData, size);
|
||||
outData = compressedData.data();
|
||||
size = compressedData.size();
|
||||
}
|
||||
|
||||
fwrite(outData, sizeof(char), size, outFile);
|
||||
fflush(outFile);
|
||||
fclose(outFile);
|
||||
}
|
||||
fclose(rom);
|
||||
|
||||
return result;
|
||||
}
|
||||
39
OTRGui/src/impl/baserom_extractor/baserom_extractor.h
Normal file
39
OTRGui/src/impl/baserom_extractor/baserom_extractor.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef EXTRACT_BASEROM_H_
|
||||
#define EXTRACT_BASEROM_H_
|
||||
|
||||
#define OOT_NTSC_10 0xEC7011B7
|
||||
#define OOT_NTSC_11 0xD43DA81F
|
||||
#define OOT_NTSC_12 0x693BA2AE
|
||||
#define OOT_PAL_10 0xB044B569
|
||||
#define OOT_PAL_11 0xB2055FBD
|
||||
#define OOT_NTSC_JP_GC_CE 0xF7F52DB8
|
||||
#define OOT_NTSC_JP_GC 0xF611F4BA
|
||||
#define OOT_NTSC_US_GC 0xF3DD35BA
|
||||
#define OOT_PAL_GC 0x09465AC3
|
||||
#define OOT_NTSC_JP_MQ 0xF43B45BA
|
||||
#define OOT_NTSC_US_MQ 0xF034001A
|
||||
#define OOT_PAL_MQ 0x1D4136F3
|
||||
#define OOT_PAL_GC_DBG1 0x871E1C92 // 03-21-2002 build
|
||||
#define OOT_PAL_GC_DBG2 0x87121EFE // 03-13-2002 build
|
||||
#define OOT_PAL_GC_MQ_DBG 0x917D18F6
|
||||
#define OOT_IQUE_TW 0x3D81FB3E
|
||||
#define OOT_IQUE_CN 0xB1E1E07B
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
struct RomVersion {
|
||||
std::string version = "None";
|
||||
std::string error = "None";
|
||||
std::string listPath = "None";
|
||||
int offset;
|
||||
uint32_t crc;
|
||||
};
|
||||
|
||||
struct WriteResult {
|
||||
std::string error = "None";
|
||||
};
|
||||
|
||||
WriteResult ExtractBaserom(const char* filePath);
|
||||
RomVersion GetVersion(FILE * rom);
|
||||
|
||||
#endif
|
||||
29
OTRGui/src/impl/baserom_extractor/yaz0/readwrite.h
Normal file
29
OTRGui/src/impl/baserom_extractor/yaz0/readwrite.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef __READWRITE_H__
|
||||
#define __READWRITE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* variables */
|
||||
union {
|
||||
uint32_t u;
|
||||
float f;
|
||||
} __u32_f32_union__;
|
||||
|
||||
#define U32(x) \
|
||||
((uint32_t)((((uint8_t*)(x))[0] << 24) | (((uint8_t*)(x))[1] << 16) | \
|
||||
(((uint8_t*)(x))[2] << 8) | ((uint8_t*)(x))[3]))
|
||||
#define U16(x) ((uint16_t)(((*((uint8_t*)(x))) << 8) | ((uint8_t*)(x))[1]))
|
||||
#define U8(x) ((uint8_t)((uint8_t*)(x))[0])
|
||||
#define S32(x) ((int32_t)(U32(x)))
|
||||
#define S16(x) ((int16_t)(U16(x)))
|
||||
#define F32(x) (((__u32_f32_union__.u = U32(x)) & 0) + __u32_f32_union__.f)
|
||||
|
||||
#define W32(x, v) \
|
||||
{ \
|
||||
*((uint8_t*)x + 3) = ((v)&0xFF); \
|
||||
*((uint8_t*)x + 2) = (((v) >> 8) & 0xFF); \
|
||||
*((uint8_t*)x + 1) = (((v) >> 16) & 0xFF); \
|
||||
*((uint8_t*)x + 0) = (((v) >> 24) & 0xFF); \
|
||||
}
|
||||
|
||||
#endif
|
||||
227
OTRGui/src/impl/baserom_extractor/yaz0/yaz0.cpp
Normal file
227
OTRGui/src/impl/baserom_extractor/yaz0/yaz0.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <list>
|
||||
#include "readwrite.h"
|
||||
|
||||
#include "yaz0.h"
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
|
||||
/* internal declarations */
|
||||
int yaz0_encode_internal(const u8* src, int srcSize, u8* Data);
|
||||
|
||||
int yaz0_get_size(u8* src) { return U32(src + 0x4); }
|
||||
|
||||
u32 toDWORD(u32 d) {
|
||||
u8 w1 = d & 0xFF;
|
||||
u8 w2 = (d >> 8) & 0xFF;
|
||||
u8 w3 = (d >> 16) & 0xFF;
|
||||
u8 w4 = d >> 24;
|
||||
return (w1 << 24) | (w2 << 16) | (w3 << 8) | w4;
|
||||
}
|
||||
|
||||
// simple and straight encoding scheme for Yaz0
|
||||
u32 longest_match_brute(const u8* src, int size, int pos, u32* pMatchPos) {
|
||||
int startPos = pos - 0x1000;
|
||||
int max_match_size = size - pos;
|
||||
u32 best_match_size = 0;
|
||||
u32 best_match_pos = 0;
|
||||
|
||||
if (max_match_size < 3) return 0;
|
||||
|
||||
if (startPos < 0) startPos = 0;
|
||||
|
||||
if (max_match_size > 0x111) max_match_size = 0x111;
|
||||
|
||||
for (int i = startPos; i < pos; i++) {
|
||||
int current_size;
|
||||
for (current_size = 0; current_size < max_match_size; current_size++) {
|
||||
if (src[i + current_size] != src[pos + current_size]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (current_size > best_match_size) {
|
||||
best_match_size = current_size;
|
||||
best_match_pos = i;
|
||||
if (best_match_size == 0x111) break;
|
||||
}
|
||||
}
|
||||
*pMatchPos = best_match_pos;
|
||||
return best_match_size;
|
||||
}
|
||||
|
||||
u32 longest_match_rabinkarp(const u8* src, int size, int pos, u32* match_pos) {
|
||||
int startPos = pos - 0x1000;
|
||||
int max_match_size = size - pos;
|
||||
u32 best_match_size = 0;
|
||||
u32 best_match_pos = 0;
|
||||
|
||||
if (max_match_size < 3) return 0;
|
||||
|
||||
if (startPos < 0) startPos = 0;
|
||||
|
||||
if (max_match_size > 0x111) max_match_size = 0x111;
|
||||
|
||||
int find_hash = src[pos] << 16 | src[pos + 1] << 8 | src[pos + 2];
|
||||
int current_hash = src[startPos] << 16 | src[startPos + 1] << 8 | src[startPos + 2];
|
||||
|
||||
for (int i = startPos; i < pos; i++) {
|
||||
if(current_hash == find_hash) {
|
||||
int current_size;
|
||||
for (current_size = 3; current_size < max_match_size; current_size++) {
|
||||
if (src[i + current_size] != src[pos + current_size]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (current_size > best_match_size) {
|
||||
best_match_size = current_size;
|
||||
best_match_pos = i;
|
||||
if (best_match_size == 0x111) break;
|
||||
}
|
||||
}
|
||||
current_hash = (current_hash << 8 | src[i + 3]) & 0xFFFFFF;
|
||||
}
|
||||
*match_pos = best_match_pos;
|
||||
|
||||
return best_match_size;
|
||||
}
|
||||
|
||||
int yaz0_encode_internal(const u8* src, int srcSize, u8* Data) {
|
||||
int srcPos = 0;
|
||||
|
||||
int bitmask = 0x80;
|
||||
u8 currCodeByte = 0;
|
||||
int currCodeBytePos = 0;
|
||||
int pos = currCodeBytePos + 1;
|
||||
|
||||
while (srcPos < srcSize) {
|
||||
u32 numBytes;
|
||||
u32 matchPos;
|
||||
|
||||
numBytes = longest_match_rabinkarp(src, srcSize, srcPos, &matchPos);
|
||||
//fprintf(stderr, "pos %x len %x pos %x\n", srcPos, (int)numBytes, (int)matchPos);
|
||||
if (numBytes < 3) {
|
||||
//fprintf(stderr, "single byte %02x\n", src[srcPos]);
|
||||
Data[pos++] = src[srcPos++];
|
||||
currCodeByte |= bitmask;
|
||||
} else {
|
||||
// RLE part
|
||||
u32 dist = srcPos - matchPos - 1;
|
||||
|
||||
if (numBytes >= 0x12) // 3 byte encoding
|
||||
{
|
||||
Data[pos++] = dist >> 8; // 0R
|
||||
Data[pos++] = dist & 0xFF; // FF
|
||||
if (numBytes > 0xFF + 0x12) numBytes = 0xFF + 0x12;
|
||||
Data[pos++] = numBytes - 0x12;
|
||||
} else // 2 byte encoding
|
||||
{
|
||||
Data[pos++] = ((numBytes - 2) << 4) | (dist >> 8);
|
||||
Data[pos++] = dist & 0xFF;
|
||||
}
|
||||
srcPos += numBytes;
|
||||
}
|
||||
bitmask >>= 1;
|
||||
// write eight codes
|
||||
if (!bitmask) {
|
||||
Data[currCodeBytePos] = currCodeByte;
|
||||
currCodeBytePos = pos++;
|
||||
|
||||
currCodeByte = 0;
|
||||
bitmask = 0x80;
|
||||
}
|
||||
}
|
||||
if (bitmask) {
|
||||
Data[currCodeBytePos] = currCodeByte;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> yaz0_encode_fast(const u8* src, int src_size) {
|
||||
std::vector<uint8_t> buffer;
|
||||
std::vector<std::list<uint32_t>> lut;
|
||||
lut.resize(0x1000000);
|
||||
|
||||
for (int i = 0; i < src_size - 3; ++i) {
|
||||
lut[src[i + 0] << 16 | src[i + 1] << 8 | src[i + 2]].push_back(i);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> yaz0_encode(const u8* src, int src_size) {
|
||||
std::vector<uint8_t> buffer(src_size * 10 / 8 + 16);
|
||||
u8* dst = buffer.data();
|
||||
|
||||
// write 4 bytes yaz0 header
|
||||
memcpy(dst, "Yaz0", 4);
|
||||
|
||||
// write 4 bytes uncompressed size
|
||||
W32(dst + 4, src_size);
|
||||
|
||||
// encode
|
||||
int dst_size = yaz0_encode_internal(src, src_size, dst + 16);
|
||||
int aligned_size = (dst_size + 31) & -16;
|
||||
buffer.resize(aligned_size);
|
||||
|
||||
#if 0
|
||||
std::vector<uint8_t> decompressed(src_size);
|
||||
yaz0_decode(buffer.data(), decompressed.data(), src_size);
|
||||
if(memcmp(src, decompressed.data(), src_size)) {
|
||||
fprintf(stderr, "Decompressed buffer is different from original\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void yaz0_decode(const uint8_t* source, uint8_t* decomp, int32_t decompSize) {
|
||||
uint32_t srcPlace = 0, dstPlace = 0;
|
||||
uint32_t i, dist, copyPlace, numBytes;
|
||||
uint8_t codeByte, byte1, byte2;
|
||||
uint8_t bitCount = 0;
|
||||
|
||||
source += 0x10;
|
||||
while (dstPlace < decompSize) {
|
||||
/* If there are no more bits to test, get a new byte */
|
||||
if (!bitCount) {
|
||||
codeByte = source[srcPlace++];
|
||||
bitCount = 8;
|
||||
}
|
||||
|
||||
/* If bit 7 is a 1, just copy 1 byte from source to destination */
|
||||
/* Else do some decoding */
|
||||
if (codeByte & 0x80) {
|
||||
decomp[dstPlace++] = source[srcPlace++];
|
||||
} else {
|
||||
/* Get 2 bytes from source */
|
||||
byte1 = source[srcPlace++];
|
||||
byte2 = source[srcPlace++];
|
||||
|
||||
/* Calculate distance to move in destination */
|
||||
/* And the number of bytes to copy */
|
||||
dist = ((byte1 & 0xF) << 8) | byte2;
|
||||
copyPlace = dstPlace - (dist + 1);
|
||||
numBytes = byte1 >> 4;
|
||||
|
||||
/* Do more calculations on the number of bytes to copy */
|
||||
if (!numBytes)
|
||||
numBytes = source[srcPlace++] + 0x12;
|
||||
else
|
||||
numBytes += 2;
|
||||
|
||||
/* Copy data from a previous point in destination */
|
||||
/* to current point in destination */
|
||||
for (i = 0; i < numBytes; i++) decomp[dstPlace++] = decomp[copyPlace++];
|
||||
}
|
||||
|
||||
/* Set up for the next read cycle */
|
||||
codeByte = codeByte << 1;
|
||||
bitCount--;
|
||||
}
|
||||
}
|
||||
6
OTRGui/src/impl/baserom_extractor/yaz0/yaz0.h
Normal file
6
OTRGui/src/impl/baserom_extractor/yaz0/yaz0.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
void yaz0_decode(const uint8_t* src, uint8_t* dest, int32_t destsize);
|
||||
std::vector<uint8_t> yaz0_encode(const uint8_t* src, int src_size);
|
||||
102
OTRGui/src/impl/extractor/extractor.cpp
Normal file
102
OTRGui/src/impl/extractor/extractor.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include "extractor.h"
|
||||
#include <string>
|
||||
|
||||
#include "impl.h"
|
||||
#include "utils/mutils.h"
|
||||
#include <thread>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PLATFORM Platforms::WINDOWS
|
||||
#else
|
||||
#define PLATFORM Platforms::LINUX
|
||||
#endif
|
||||
namespace Util = MoonUtils;
|
||||
|
||||
static int maxResources = 0;
|
||||
static int extractedResources = 0;
|
||||
bool buildingOtr = false;
|
||||
int skipFrames = 0;
|
||||
|
||||
bool isWindows() {
|
||||
return (PLATFORM == Platforms::WINDOWS);
|
||||
}
|
||||
|
||||
void BuildOTR(const std::string output) {
|
||||
Util::copy("tmp/baserom/Audiobank", "Extract/Audiobank");
|
||||
Util::copy("tmp/baserom/Audioseq", "Extract/Audioseq");
|
||||
Util::copy("tmp/baserom/Audiotable", "Extract/Audiotable");
|
||||
|
||||
Util::copy("assets/game/", "Extract/assets/");
|
||||
|
||||
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out") + " botr -se OTR";
|
||||
ProcessResult result = NativeFS->LaunchProcess(execStr);
|
||||
if(result.exitCode != 0) {
|
||||
std::cout << "\nError when building the OTR file with error code: " << result.exitCode << " !" << std::endl;
|
||||
std::cout << "Aborting...\n" << std::endl;
|
||||
}
|
||||
setCurrentStep("Done!");
|
||||
|
||||
if (output == ".") return;
|
||||
const std::string outputPath = MoonUtils::join(output, "oot.otr");
|
||||
if(MoonUtils::exists(outputPath)) MoonUtils::rm(outputPath);
|
||||
|
||||
MoonUtils::copy("oot.otr", outputPath);
|
||||
}
|
||||
|
||||
void ExtractFile(std::string xmlPath, std::string outPath, std::string outSrcPath) {
|
||||
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out");
|
||||
std::string args = Util::format(" e -eh -i %s -b tmp/baserom/ -o %s -osf %s -gsf 1 -rconf assets/extractor/Config.xml -se OTR %s", xmlPath.c_str(), outPath.c_str(), outSrcPath.c_str(), xmlPath.find("overlays") != std::string::npos ? "--static" : "");
|
||||
ProcessResult result = NativeFS->LaunchProcess(execStr + args);
|
||||
|
||||
if (result.exitCode != 0) {
|
||||
std::cout << "\nError when extracting the ROM with error code: " << result.exitCode << " !" << std::endl;
|
||||
std::cout << "Aborting...\n" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractFunc(std::string fullPath) {
|
||||
std::vector<std::string> path = Util::split(fullPath, Util::pathSeparator());
|
||||
std::string outPath = Util::join(Util::join("assets/extractor/xmls/output", path[4]), Util::basename(fullPath));
|
||||
Util::mkdir(outPath);
|
||||
ExtractFile(fullPath, outPath, outPath);
|
||||
setCurrentStep("Extracting: " + Util::basename(fullPath));
|
||||
extractedResources++;
|
||||
}
|
||||
|
||||
void startWorker() {
|
||||
std::string path = "assets/extractor/xmls";
|
||||
std::vector<std::string> files;
|
||||
Util::dirscan(path, files);
|
||||
std::vector<std::string> xmlFiles;
|
||||
for(auto &file : files) {
|
||||
if (file.find(".xml") != std::string::npos) xmlFiles.push_back(file);
|
||||
}
|
||||
|
||||
for (auto& file : xmlFiles) {
|
||||
if(single_thread) {
|
||||
ExtractFunc(file);
|
||||
} else {
|
||||
std::thread thread_object(ExtractFunc, file);
|
||||
thread_object.detach();
|
||||
}
|
||||
}
|
||||
|
||||
maxResources = xmlFiles.size();
|
||||
}
|
||||
|
||||
void updateWorker(const std::string& output) {
|
||||
if (maxResources > 0 && !buildingOtr && extractedResources >= maxResources) {
|
||||
setCurrentStep("Building OTR...");
|
||||
if (skipFrames < 3) {
|
||||
skipFrames++;
|
||||
return;
|
||||
}
|
||||
buildingOtr = true;
|
||||
if (single_thread){
|
||||
BuildOTR(output);
|
||||
return;
|
||||
}
|
||||
std::thread otr(BuildOTR, output);
|
||||
otr.detach();
|
||||
}
|
||||
}
|
||||
9
OTRGui/src/impl/extractor/extractor.h
Normal file
9
OTRGui/src/impl/extractor/extractor.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
enum Platforms {
|
||||
WINDOWS, LINUX
|
||||
};
|
||||
|
||||
void startWorker();
|
||||
void updateWorker(const std::string& output);
|
||||
82
OTRGui/src/impl/fix_baserom/fix_baserom.cpp
Normal file
82
OTRGui/src/impl/fix_baserom/fix_baserom.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "fix_baserom.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
|
||||
#include "md5/md5.h"
|
||||
|
||||
#define ROM_SIZE 0x3600000
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#define __bswap_32 _byteswap_ulong
|
||||
#define bswap_32 _byteswap_ulong
|
||||
#define __bswap_16 _byteswap_ushort
|
||||
#endif
|
||||
|
||||
int fix_baserom(const char* baserom_path, const char* output_path) {
|
||||
FILE* currentFile = fopen(baserom_path, "rb");
|
||||
char md5[16];
|
||||
|
||||
if (currentFile != nullptr) md5File(currentFile, md5);
|
||||
|
||||
currentFile = fopen(baserom_path, "rb");
|
||||
if (currentFile != NULL) {
|
||||
uint8_t firstByte = 0x00;
|
||||
|
||||
if (fread(&firstByte, sizeof(uint8_t), 1, currentFile) != 1) return 1;
|
||||
fseek(currentFile, 0, SEEK_SET);
|
||||
FILE* outFile = fopen(output_path, "wb");
|
||||
|
||||
// Little Endian N64 Rom
|
||||
|
||||
if (firstByte == 0x40) {
|
||||
uint32_t currentWord;
|
||||
|
||||
for (uint32_t i = 0; i < ROM_SIZE / 4; i++) {
|
||||
if (fread(¤tWord, sizeof(uint32_t), 1, currentFile) != 1) {
|
||||
fprintf(stderr, "Failed to read data from rom file\n");
|
||||
}
|
||||
currentWord = __bswap_32(currentWord);
|
||||
if (fwrite(¤tWord, sizeof(uint32_t), 1, outFile) != 1) {
|
||||
fprintf(stderr, "Failed to write to new rom file.\n");
|
||||
}
|
||||
}
|
||||
} else if (firstByte == 0x37) { // Byte Swapped
|
||||
uint16_t currentShort;
|
||||
|
||||
for (uint32_t i = 0; i < ROM_SIZE / 2; i++) {
|
||||
if (fread(¤tShort, sizeof(uint16_t), 1, currentFile) != 1) {
|
||||
fprintf(stderr, "Failed to read data from rom file\n");
|
||||
return 1;
|
||||
}
|
||||
currentShort = __bswap_16(currentShort);
|
||||
if (fread(¤tShort, sizeof(uint16_t), 1, outFile) != 1) {
|
||||
fprintf(stderr, "Failed to write to new rom file.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else { // Big Endian
|
||||
void* data = malloc(ROM_SIZE);
|
||||
if (data == NULL) {
|
||||
fprintf(stderr, "Failed to allocate memory for new baserom.\n");
|
||||
return 1;
|
||||
}
|
||||
if (fread(data, ROM_SIZE, 1, currentFile) != 1) {
|
||||
fprintf(stderr, "Failed to read data from rom file\n");
|
||||
return 1;
|
||||
}
|
||||
if (fread(data, ROM_SIZE, 1, outFile) != 1) {
|
||||
fprintf(stderr, "Failed to write to new rom file.\n");
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
fseek(outFile, 0x3E, SEEK_SET);
|
||||
fputc('P', outFile); // Patch the rom header to be 'PAL'
|
||||
fclose(outFile);
|
||||
fclose(currentFile);
|
||||
}
|
||||
}
|
||||
3
OTRGui/src/impl/fix_baserom/fix_baserom.h
Normal file
3
OTRGui/src/impl/fix_baserom/fix_baserom.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
int fix_baserom(const char* baserom_path, const char* output_path);
|
||||
307
OTRGui/src/impl/fix_baserom/md5/md5.c
Normal file
307
OTRGui/src/impl/fix_baserom/md5/md5.c
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_OPENSSL
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
* The basic MD5 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1321 definitions for
|
||||
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
|
||||
* implementation.
|
||||
*/
|
||||
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
|
||||
#define H(x, y, z) (((x) ^ (y)) ^ (z))
|
||||
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
|
||||
/*
|
||||
* The MD5 transformation for all four rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, t, s) \
|
||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
|
||||
(a) += (b);
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them in a
|
||||
* properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned memory
|
||||
* accesses is just an optimization. Nothing will break if it fails to detect
|
||||
* a suitable architecture.
|
||||
*
|
||||
* Unfortunately, this optimization may be a C strict aliasing rules violation
|
||||
* if the caller's data buffer has effective type that cannot be aliased by
|
||||
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
|
||||
* inlined into a calling function, or with future and dangerously advanced
|
||||
* link-time optimizations. For the time being, keeping these MD5 routines in
|
||||
* their own translation unit avoids the problem.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) \
|
||||
(*(MD5_u32plus *)&ptr[(n) * 4])
|
||||
#define GET(n) \
|
||||
SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = \
|
||||
(MD5_u32plus)ptr[(n) * 4] | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
|
||||
#define GET(n) \
|
||||
(ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update the bit
|
||||
* counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
const unsigned char *ptr;
|
||||
MD5_u32plus a, b, c, d;
|
||||
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
|
||||
|
||||
ptr = (const unsigned char *)data;
|
||||
|
||||
a = ctx->a;
|
||||
b = ctx->b;
|
||||
c = ctx->c;
|
||||
d = ctx->d;
|
||||
|
||||
do {
|
||||
saved_a = a;
|
||||
saved_b = b;
|
||||
saved_c = c;
|
||||
saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
||||
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
||||
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
||||
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
||||
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
||||
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
||||
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
||||
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
||||
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
||||
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
||||
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
||||
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
||||
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
||||
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
||||
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
||||
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
||||
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
||||
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
||||
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
||||
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
||||
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
||||
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
||||
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
||||
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
||||
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
||||
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
||||
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
||||
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
||||
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
||||
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
||||
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
||||
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
|
||||
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
||||
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
|
||||
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
||||
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
||||
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
||||
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
||||
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
||||
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
||||
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
||||
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
|
||||
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
||||
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
||||
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
||||
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
||||
|
||||
/* Round 4 */
|
||||
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
||||
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
||||
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
||||
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
||||
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
||||
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
||||
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
||||
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
||||
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
||||
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
||||
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
||||
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
||||
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
||||
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
||||
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
||||
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void MD5_Init(MD5_CTX *ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
MD5_u32plus saved_lo;
|
||||
unsigned long used, available;
|
||||
|
||||
saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
used = saved_lo & 0x3f;
|
||||
|
||||
if (used) {
|
||||
available = 64 - used;
|
||||
|
||||
if (size < available) {
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char *)data + available;
|
||||
size -= available;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64) {
|
||||
data = body(ctx, data, size & ~(unsigned long)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
#define OUT(dst, src) \
|
||||
(dst)[0] = (unsigned char)(src); \
|
||||
(dst)[1] = (unsigned char)((src) >> 8); \
|
||||
(dst)[2] = (unsigned char)((src) >> 16); \
|
||||
(dst)[3] = (unsigned char)((src) >> 24);
|
||||
|
||||
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
||||
{
|
||||
unsigned long used, available;
|
||||
|
||||
used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
available = 64 - used;
|
||||
|
||||
if (available < 8) {
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
OUT(&ctx->buffer[56], ctx->lo)
|
||||
OUT(&ctx->buffer[60], ctx->hi)
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
OUT(&result[0], ctx->a)
|
||||
OUT(&result[4], ctx->b)
|
||||
OUT(&result[8], ctx->c)
|
||||
OUT(&result[12], ctx->d)
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void md5File(FILE* file, char* outBuffer) {
|
||||
char buffer[1024];
|
||||
size_t inputSize = 0;
|
||||
fseek(file, 0, SEEK_SET);
|
||||
MD5_CTX ctx;
|
||||
MD5_Init(&ctx);
|
||||
|
||||
|
||||
while ((inputSize = fread(buffer, 1, 1024, file)) > 0) {
|
||||
MD5_Update(&ctx, (char*)buffer, inputSize);
|
||||
}
|
||||
//char buffer2[16];
|
||||
MD5_Final(outBuffer, &ctx);
|
||||
}
|
||||
58
OTRGui/src/impl/fix_baserom/md5/md5.h
Normal file
58
OTRGui/src/impl/fix_baserom/md5/md5.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md5.c for more information.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/md5.h>
|
||||
#elif !defined(_MD5_H)
|
||||
#define _MD5_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned int MD5_u32plus;
|
||||
|
||||
typedef struct {
|
||||
MD5_u32plus lo, hi;
|
||||
MD5_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
MD5_u32plus block[16];
|
||||
} MD5_CTX;
|
||||
|
||||
extern void MD5_Init(MD5_CTX* ctx);
|
||||
extern void MD5_Update(MD5_CTX* ctx, const void* data, unsigned long size);
|
||||
extern void MD5_Final(unsigned char* result, MD5_CTX* ctx);
|
||||
|
||||
extern void md5File(FILE* inFile, char* outBuffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
20
OTRGui/src/impl/fs-bridge/fs-bridge.h
Normal file
20
OTRGui/src/impl/fs-bridge/fs-bridge.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#define NULLSTR "None"
|
||||
|
||||
enum class LaunchType {
|
||||
FILE, FOLDER
|
||||
};
|
||||
|
||||
struct ProcessResult {
|
||||
int exitCode;
|
||||
};
|
||||
|
||||
class FSBridge {
|
||||
public:
|
||||
virtual void InitBridge() = 0;
|
||||
virtual ProcessResult LaunchProcess(std::string cmd) = 0;
|
||||
virtual std::string LaunchFileExplorer(LaunchType type) = 0;
|
||||
};
|
||||
37
OTRGui/src/impl/fs-bridge/linux/fs-linux.cpp
Normal file
37
OTRGui/src/impl/fs-bridge/linux/fs-linux.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "fs-linux.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <stdio.h>
|
||||
#include "utils/mutils.h"
|
||||
#include "portable-file-dialogs.h"
|
||||
|
||||
#define DEFAULT_PATH "~"
|
||||
|
||||
void LinuxBridge::InitBridge() {}
|
||||
|
||||
ProcessResult LinuxBridge::LaunchProcess(std::string cmd) {
|
||||
cmd = MoonUtils::normalize(cmd);
|
||||
std::cout << "Trying to launch: " << cmd << std::endl;
|
||||
ProcessResult result = { };
|
||||
result.exitCode = WEXITSTATUS(system(cmd.c_str()));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string LinuxBridge::LaunchFileExplorer(LaunchType type) {
|
||||
if(type == LaunchType::FILE){
|
||||
auto file = pfd::open_file("Open OoT Baserom", DEFAULT_PATH,
|
||||
{ "Rom Files (.z64 .n64)", "*.z64 *.n64", "All Files", "*" },
|
||||
pfd::opt::force_path
|
||||
);
|
||||
std::vector<std::string> files = file.result();
|
||||
if(!files.empty()) return files[0];
|
||||
}
|
||||
|
||||
if(type == LaunchType::FOLDER){
|
||||
auto dir = pfd::select_folder("Select any directory", DEFAULT_PATH).result();
|
||||
if(!dir.empty()) return dir;
|
||||
}
|
||||
|
||||
return "None";
|
||||
}
|
||||
#endif
|
||||
9
OTRGui/src/impl/fs-bridge/linux/fs-linux.h
Normal file
9
OTRGui/src/impl/fs-bridge/linux/fs-linux.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../fs-bridge.h"
|
||||
|
||||
class LinuxBridge : public FSBridge {
|
||||
void InitBridge() override;
|
||||
ProcessResult LaunchProcess(std::string cmd) override;
|
||||
std::string LaunchFileExplorer(LaunchType type) override;
|
||||
};
|
||||
1730
OTRGui/src/impl/fs-bridge/linux/portable-file-dialogs.h
Normal file
1730
OTRGui/src/impl/fs-bridge/linux/portable-file-dialogs.h
Normal file
File diff suppressed because it is too large
Load Diff
97
OTRGui/src/impl/fs-bridge/windows/fs-windows.cpp
Normal file
97
OTRGui/src/impl/fs-bridge/windows/fs-windows.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "fs-windows.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#include <Windows.h>
|
||||
#include <ShObjIdl.h>
|
||||
#include <stdio.h>
|
||||
#include "utils/mutils.h"
|
||||
|
||||
void WindowsBridge::InitBridge() {}
|
||||
|
||||
ProcessResult WindowsBridge::LaunchProcess(std::string cmd) {
|
||||
cmd = MoonUtils::normalize(cmd);
|
||||
std::cout << "Trying to launch: " << cmd << std::endl;
|
||||
ProcessResult result = { };
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
DWORD exit_code;
|
||||
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
char cwd[256];
|
||||
getcwd(cwd, 256);
|
||||
|
||||
// Start the child process.
|
||||
if (!CreateProcess(NULL, // No module name (use command line)
|
||||
LPSTR(cmd.c_str()), // Command line
|
||||
NULL, // Process handle not inheritable
|
||||
NULL, // Thread handle not inheritable
|
||||
FALSE, // Set handle inheritance to FALSE
|
||||
0, // No creation flags
|
||||
NULL, // Use parent's environment block
|
||||
NULL, // Use parent's starting directory
|
||||
&si, // Pointer to STARTUPINFO structure
|
||||
&pi
|
||||
)) {
|
||||
result.exitCode = GetLastError();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Wait until child process exits.
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
GetExitCodeProcess(pi.hProcess, &exit_code);
|
||||
|
||||
result.exitCode = static_cast<int>(exit_code);
|
||||
|
||||
// Close process and thread handles.
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
std::string WindowsBridge::LaunchFileExplorer(LaunchType type) {
|
||||
std::string path = "None";
|
||||
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
if (!SUCCEEDED(hr)) return path;
|
||||
IFileOpenDialog* pFileOpen;
|
||||
|
||||
// Create the FileOpenDialog object.
|
||||
hr = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_ALL,
|
||||
IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
|
||||
if (type == LaunchType::FOLDER) {
|
||||
DWORD dwOptions;
|
||||
pFileOpen->GetOptions(&dwOptions);
|
||||
pFileOpen->SetOptions(dwOptions | FOS_PICKFOLDERS);
|
||||
}
|
||||
if (!SUCCEEDED(hr)) {
|
||||
CoUninitialize();
|
||||
return path;
|
||||
}
|
||||
|
||||
hr = pFileOpen->Show(nullptr);
|
||||
|
||||
if (!SUCCEEDED(hr)) {
|
||||
pFileOpen->Release();
|
||||
return path;
|
||||
}
|
||||
|
||||
IShellItem* pItem;
|
||||
hr = pFileOpen->GetResult(&pItem);
|
||||
if (!SUCCEEDED(hr)) return path;
|
||||
|
||||
PWSTR pszFilePath;
|
||||
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
|
||||
|
||||
// Display the file name to the user.
|
||||
if (SUCCEEDED(hr)) {
|
||||
path = MoonUtils::narrow(std::wstring(pszFilePath));
|
||||
CoTaskMemFree(pszFilePath);
|
||||
}
|
||||
pItem->Release();
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
9
OTRGui/src/impl/fs-bridge/windows/fs-windows.h
Normal file
9
OTRGui/src/impl/fs-bridge/windows/fs-windows.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../fs-bridge.h"
|
||||
|
||||
class WindowsBridge : public FSBridge {
|
||||
void InitBridge() override;
|
||||
ProcessResult LaunchProcess(std::string cmd) override;
|
||||
std::string LaunchFileExplorer(LaunchType type) override;
|
||||
};
|
||||
Reference in New Issue
Block a user