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)Nintendo All rights reserved.
These coded instructions, statements, and computer programs contain proprietary
information of Nintendo and/or its licensed developers and are protected by
national and international copyright laws. 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.
The content herein is highly confidential and should be handled accordingly.
*--------------------------------------------------------------------------------*/
#include <string.h>
#if defined(CAFE) || defined(NN_PLATFORM_CTR)
#endif
static UniquePtr<unsigned char[]> g_olddata;
static size_t g_olddata_size;
static UniquePtr<unsigned char[]> g_newdata;
static size_t g_newdata_size;
static ReallocOutputStream::UniquePtrType g_patchdata;
static size_t g_patchdata_size;
// 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_olddata_size = 1024 * 128;
nlib_printf("oldData size = %" PRIuS " bytes\n", g_olddata_size);
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_newdata_size = 1024 * 1024;
nlib_printf("newData size = %" PRIuS " bytes\n", g_newdata_size);
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_olddata_size, g_newdata.get(), g_newdata_size);
if (!nlib_is_error(e)) {
g_patchdata_size = ostr.Release(&g_patchdata);
nlib_printf("patch size = %" PRIuS " bytes\n", g_patchdata_size);
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_olddata_size, g_patchdata.get(), g_patchdata_size);
if (!nlib_is_error(e)) {
ReallocOutputStream::UniquePtrType result;
size_t resultSize = ostr.Release(&result);
nlib_printf("Checking the data .... ");
if (resultSize == g_newdata_size &&
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_nmalloc_settings = { 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_nmalloc_settings = { heapmem, heapmem_size, 0 };
#endif
#endif
bool SampleMain(int, char**) {
return SetupOldData() && SetupNewData() && MakeBsDiffZ() && ApplyBsPatchZ();
}
NLIB_MAINFUNC