← [Chapter 1] | [Chapter 3] → |
The file structure for DS Protect libraries are as follows.
AMProtect.h | Header file that contains the detection function prototypes. |
AMProtectRa.a |
Detection function library. You can use this by adding it to the project's Libraries folder, but if at all possible we recommend integrating it into an overlay module that does not reside in memory for very long. |
#include "AMProtect.h"
// Functions that return TRUE when detection succeeds, then execute the specified function
u32 AM_IsMagiconA1( void(*func)() );
u32 AM_IsMagiconA2( void(*func)() );
u32 AM_IsMagiconA3( void(*func)() );
// Functions that return TRUE when detection fails, then execute the specified function
u32 AM_IsNotMagiconA1( void(*func)() );
u32 AM_IsNotMagiconA2( void(*func)() );
u32 AM_IsNotMagiconA3( void(*func)() );
(These functions are macros in FINALROM versions. They are functions in DEBUG and RELEASE versions.)
void(*func)() | Address of void(*func)() -type function to run when detection succeeds or fails.After the specified function is run, control returns to the original process. When NULL is specified, a value indicating the detection result is returned without doing anything else.Although you can specify NULL for the argument, we recommend specifying some function for stronger protection. |
Returns a u32
-type TRUE
(nonzero) or FALSE
(0) as the result of detection.
Detects whether the program is running on devices other than a Nintendo DS system, such as a piracy device or an emulator. For information on detectable piracy devices and emulators, and support of official development environments, see sections 1.2.1 Piracy Devices Whose Detection Has Been Confirmed and 1.2.2 Emulators Whose Detection Has Been Confirmed.
When using DS Protect in a program, you must always use all three functions as a set.
AM_IsMagiconA1()
or AM_IsNotMagiconA1()
// Detection function for general piracy devices and some emulators.AM_IsMagiconA2()
or AM_IsNotMagiconA2()
// Emulator detection function. AM_IsMagiconA3()
or AM_IsNotMagiconA3()
// Dummy function that does not actually detect anything No function groups are thread-safe.
When an AM_IsMagiconA*
function is called and detection succeeds, the program is running in an illegal environment. The function specified in the argument is run and TRUE
is returned. If nothing is detected, the function specified in the argument is not run and FALSE
is returned.
When an AM_IsNotMagiconA*
function is called and nothing is detected, the function specified in the argument is run and TRUE
is returned. If detection succeeds, the function specified in the argument is not run and FALSE
is returned.
For each detection function, you can specify the address of a void(*func)()
-type function to run when detection succeeds or fails. Once the specified function is run, control returns.
You can call functions in any order in the program, but you must strictly observe the following rules to prevent DS Protect from being easily cracked.
A1
-suffixed function, an A2
-suffixed function, and an A3
-suffixed function once each before repeating any of them. (This is called one set.) A1
, A2
, and A3
functions in one set. Is
and IsNot
versions of functions; for example, using both AM_IsMagiconA1
and AM_IsNotMagiconA1
. (In other words, we do not recommend that you use only the AM_IsMagiconA1
, A2
, and A3
functions or only the AM_IsNotMagiconA1
, A2
, and A3
functions.) Behavior on the program side will differ depending on the build option if either the AM_IsMagiconA1
or AM_IsNotMagiconA1
detection function is called when a call to the OS_GetLockID
function will return OS_LOCK_ID_ERROR
.
Build Option | Operating Environment | Run-Time Behavior |
---|---|---|
DEBUG | Official product | Freezes |
Debugger (IS-NITRO-DEBUGGER) | Stops and displays log (AMProtect.h:91 Panic:lock ID get error. ) |
|
Piracy device | Freezes | |
RELEASE | Official product | Freezes |
Debugger (IS-NITRO-DEBUGGER) | Stops and displays log (AMProtect.h:91 Panic:lock ID get error. ) |
|
Piracy device | Freezes | |
FINALROM | Official product | Determines environment is official |
Debugger (IS-NITRO-DEBUGGER) | Determines environment is illegal | |
Piracy device | Determines environment is illegal |
This sample is one example, which builds on section 3 Response Method Guidelines. Devise an implementation method that suits your particular program.
The following is an example implementation using an overlay module. This implementation references section 3.5.5 Bug-Inducing Protection.
//
// Normal function into which piracy device detection is integrated.
//
// Result: When program is being used illegally, generates 512-KB memory leak
// each time control passes through this function.
// Cumulative memory leak causes program to freeze.
// Embed this in some process passed through many times during the game (such as screen switching).
//
u32 HogehogeFunc(void)
{
// (Omitted)
char *pTemp = NULL;
// (Omitted)
// In an overlay, call module that includes library
FS_LoadOverlay(MI_PROCESSOR_ARM9, FS_OVERLAY_ID(OVERLAY_PROTECT));
if (AM_IsMagiconA1(NULL)) {
if (NULL == pTemp) {
pTemp = new char[0x80000];
}
}
// (Omitted)
if (AM_IsMagiconA2(NULL)) {
if (NULL == pTemp) {
pTemp = new char[0x80000];
}
}
// (Omitted)
if (AM_IsMagiconA3(NULL)) {
if (NULL == pTemp) {
pTemp = new char[0x80000];
}
}
// Unload library loaded as overlay
FS_UnloadOverlay(MI_PROCESSOR_ARM9, FS_OVERLAY_ID(OVERLAY_PROTECT));
// (Omitted)
}
The following is an implementation with reference to section 3.5.2 Menu-Type Protection.
// Function that performs normal initialization.
void Init(void)
{
gStateA = new gStateA;
gStateB = new gStateB;
gStateC = new gStateC;
}
// Function that performs invalid initialization.
void InitDummy(void)
{
gStateA = new gStateA;
gStateB = new gStateB_Dummy; // Invalid initialization
gStateC = new gStateC;
}
// (Omitted)
//
// Initialization function into which piracy device detection is integrated.
//
// Result: When program is being used illegally, performs invalid initialization.
// Although a class is initialized here, the same effect
// can be achieved even if the overlay is switched.
//
u32 FoofooInitFunc(void)
{
// (Omitted)
if (!AM_IsNotMagiconA1(Init)) {
InitDummy();
}
AM_IsMagiconA2(InitDummy);
AM_IsMagiconA3(InitDummy);
// (Omitted)
}
The implementation shown below is equivalent to the wrapper function described in step 4 in section How to Use above. Never adopt this method.
// ※※※※※ Usage Prohibited ※※※※※
//
// Piracy device detection function.
//
// This is an implementation of a wrapper function type that combines the three types of detection functions.
// Never actually use this method.
//
u32 isMagiconPresent(void)
{
u32 r;
r += AM_IsMagiconA1(NULL);
r += AM_IsMagiconA2(NULL);
r += AM_IsMagiconA3(NULL);
return r;
}
// (Omitted)
// Flag storing piracy device detection results
bool gIsMagiconFlag = false;
// (Omitted)
//
// Normal function into which piracy device detection is integrated.
//
u32 HogeFunc(void)
{
// (Omitted)
// Call the piracy device detection function
// and store detection results in the detection results flag
if (isMagiconPresent()) {
gIsMagiconFlag = true;
}
// (Omitted)
}
// ※※※※※ Usage Prohibited ※※※※※
← [Chapter 1] | [Chapter 3] → |
CONFIDENTIAL