nlib
oss/binarypatch/binarypatch.cpp

An example explaining the creation of a binary patch by the BsDiffZ function and the application of the patch by the BsPatchZ function.

/*---------------------------------------------------------------------------*
Project: CrossRoad
Copyright (C)2012-2016 Nintendo. All rights reserved.
These coded instructions, statements, and computer programs contain
proprietary information of Nintendo of America Inc. and/or Nintendo
Company Ltd., and are protected by Federal copyright law. They may
not be disclosed to third parties or copied or duplicated in any form,
in whole or in part, without the prior written consent of Nintendo.
*---------------------------------------------------------------------------*/
#include <string.h>
#if defined(CAFE) || defined(NN_PLATFORM_CTR)
#endif
static UniquePtr<unsigned char[]> g_OldData;
static size_t g_OldDataSize;
static UniquePtr<unsigned char[]> g_NewData;
static size_t g_NewDataSize;
static ReallocOutputStream::UniquePtrType g_PatchData;
static size_t g_PatchDataSize;
// Generates the old data.
static bool SetupOldData() {
nlib_printf("setup oldData\n");
g_OldData.reset(new(std::nothrow) unsigned char[1024 * 128]);
if (!g_OldData) return false;
for (size_t i = 0; i < 1024 * 128; ++i) {
g_OldData[i] = static_cast<unsigned char>(i % 256);
}
g_OldDataSize = 1024 * 128;
nlib_printf("oldData size = %" PRIuS " bytes\n", g_OldDataSize);
return true;
}
// Generates the new data.
static bool SetupNewData() {
nlib_printf("setup newData\n");
g_NewData.reset(new(std::nothrow) unsigned char[1024 * 1024]);
if (!g_NewData) return false;
for (size_t i = 0; i < 1024 * 1024; ++i) {
g_NewData[i] = static_cast<unsigned char>(255 - i % 256);
}
g_NewDataSize = 1024 * 1024;
nlib_printf("newData size = %" PRIuS " bytes\n", g_NewDataSize);
return true;
}
static bool MakeBsDiffZ() {
// Creates the patch from the old data to the new data.
// You can also create a patch by using bsdiff_z.exe on PCs.
nlib_printf("BsDiffZ()....\n");
ReallocOutputStream ostr;
g_OldData.get(), g_OldDataSize, g_NewData.get(), g_NewDataSize);
if (!nlib_is_error(e)) {
g_PatchDataSize = ostr.Release(&g_PatchData);
nlib_printf("patch size = %" PRIuS " bytes\n", g_PatchDataSize);
return true;
} else {
nlib_printf("BsDiffZ() failed\n");
return false;
}
}
static bool ApplyBsPatchZ() {
// Before you apply the patch,
// you have to place the old data and the patch for it on the memory.
// You can also apply a patch by using bspatch_z.exe on PCs.
nlib_printf("BsPatchZ()....\n");
ReallocOutputStream ostr;
g_OldData.get(), g_OldDataSize, g_PatchData.get(), g_PatchDataSize);
if (!nlib_is_error(e)) {
ReallocOutputStream::UniquePtrType result;
size_t resultSize = ostr.Release(&result);
nlib_printf("Checking the data .... ");
if (resultSize == g_NewDataSize &&
memcmp(g_NewData.get(), result.get(), resultSize) == 0) {
nlib_printf("success\n");
return true;
} else {
nlib_printf("fail\n");
return false;
}
} else {
nlib_printf("BsPatchZ() failed\n");
return false;
}
}
//
// bsdiff in nlib uses nmalloc/nfree in libnx_oss.a.
// You have to link libnx_oss.a, and set up nmalloc.
//
#if defined(CAFE) || defined(NN_PLATFORM_CTR)
#ifdef NLIB_HAS_VIRTUALMEMORY
extern "C" const NMallocSettings g_NMallocSettings = { NULL, 1024 * 1024 * 16, 0 };
#else
const size_t heapmem_size = 1024 * 1024 * 16;
NLIB_ALIGNAS(4096) static char heapmem[heapmem_size];
extern "C" const NMallocSettings g_NMallocSettings = { heapmem, heapmem_size, 0 };
#endif
#endif
bool SampleMain(int, char**) {
return SetupOldData() && SetupNewData() && MakeBsDiffZ() && ApplyBsPatchZ();
}
NLIB_MAINFUNC