← [Chapter 1] [Chapter 3] →

2. Function Reference


2.1 File Structure

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.

2.2 AM_Is(Not)MagiconA*

Syntax

#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.)

Arguments

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.

Return Values

Returns a u32-type TRUE (nonzero) or FALSE (0) as the result of detection.

Description

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.

1) AM_IsMagiconA1() or AM_IsNotMagiconA1() // Detection function for general piracy devices and some emulators.
LockID is used in this function.
2) AM_IsMagiconA2() or AM_IsNotMagiconA2() // Emulator detection function.
3) 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.

How to Use

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.

  1. When you integrate detection processing into your program, call an A1-suffixed function, an A2-suffixed function, and an A3-suffixed function once each before repeating any of them. (This is called one set.)
  2. To make operation tests easier, we recommend using the same detection processing for each of the A1, A2, and A3 functions in one set.
  3. For complete coverage, we recommend using both the 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.)
  4. There are significant security issues in implementing a wrapper function type that incorporates all three types of functions in one function. Never do that.
  5. If possible, we recommend that you include the Nintendo-provided functions in an overlay module and call them from an overlay module.

Note

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

Sample

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)

}

Sample (Poor Implementation)

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